javascript - angularjs شرح




كيفية التعامل مع ربط تجزئة الربط في AngularJS (18)

هل يعرف أي واحد منكم كيفية التعامل مع ربط وصلة التجزئة في AngularJS ؟

لدي الترميز التالي لصفحة الأسئلة الشائعة البسيطة

<a href="#faq-1">Question 1</a>
<a href="#faq-2">Question 2</a>
<a href="#faq-3">Question 3</a>

<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="fa1-3">Question 3</h3>

عند النقر على أي من الروابط أعلاه ، تعترض AngularJS وتوجهني إلى صفحة مختلفة تمامًا (في حالتي ، صفحة 404 حيث لا توجد طرق مطابقة للروابط).

كانت فكرتي الأولى هي إنشاء مسار يطابق " / faq /: chapter " وفي التحقق من وحدة التحكم المقابلة $routeParams.chapter بعد عنصر المطابقة ثم استخدم jQuery للتمرير لأسفل إليه.

ولكن بعد ذلك ، يركع AngularJS علي مرة أخرى ويمرر إلى أعلى الصفحة على أية حال.

لذا ، أي شخص هنا فعل أي شيء مماثل في الماضي ويعرف حلا جيدا لذلك؟

تحرير: التبديل إلى html5Mode يجب أن يحل مشاكلي ولكن علينا أن ندعم IE8 + على أي حال لذا أخشى أنه ليس حلاً مقبولاً: /


أنا باستخدام AngularJS 1.3.15 ويبدو أنني لست بحاجة إلى القيام بأي شيء خاص.

https://code.angularjs.org/1.3.15/docs/api/ng/provider/ $ anchorScrollProvider

لذلك ، فإن الأعمال التالية بالنسبة لي في بلدي أتش تي أم أل:

<ul>
  <li ng-repeat="page in pages"><a ng-href="#{{'id-'+id}}">{{id}}</a>
  </li>
</ul>
<div ng-attr-id="{{'id-'+id}}" </div>

لم يكن من الضروري إجراء أي تغييرات على جهاز التحكم أو جافا سكريبت على الإطلاق.


إذا كنت تعرف الطريق دائمًا ، فيمكنك ببساطة إلحاق المرساة على النحو التالي:

href="#/route#anchorID

حيث يشير المسار إلى المسار الزاوي الحالي anchorID إلى <a id="anchorID"> مكان ما على الصفحة


احصل على ميزة التمرير بسهولة. كما يدعم التمرير المتحرك / السلس كميزة إضافية. تفاصيل مكتبة Angular Scroll :

جيثب - https://github.com/oblador/angular-scroll

Bower : bower install --save angular-scroll

npm : npm install --save angular-scroll

نسخة Minfied - فقط 9KB

التمرير السلس (التمرير المتحركة) - نعم

Scroll Spy - نعم

وثائق - ممتازة

عرض تجريبي - http://oblador.github.io/angular-scroll/

أتمنى أن يساعدك هذا.


استنادًا إلىStoyan ، توصلت إلى الحل التالي:

app.run(function($location, $anchorScroll){
    var uri = window.location.href;

    if(uri.length >= 4){

        var parts = uri.split('#!#');
        if(parts.length > 1){
            var anchor = parts[parts.length -1];
            $location.hash(anchor);
            $anchorScroll();
        }
    }
});

حصلت على هذا في منطق الطريق للتطبيق الخاص بي.

function config($routeProvider) {
  $routeProvider
    .when('/', {
      templateUrl: '/partials/search.html',
      controller: 'ctrlMain'
    })
    .otherwise({
      // Angular interferes with anchor links, so this function preserves the
      // requested hash while still invoking the default route.
      redirectTo: function() {
        // Strips the leading '#/' from the current hash value.
        var hash = '#' + window.location.hash.replace(/^#\//g, '');
        window.location.hash = hash;
        return '/' + hash;
      }
    });
}

راجع https://code.angularjs.org/1.4.10/docs/api/ngRoute/provider/ $ routeProvider

[reloadOnSearch = true] - {boolean =} - إعادة توجيه الطريق عند تغيير $ location.search () $ فقط أو $ location.hash ().

تعيين هذا إلى false لم خدعة دون كل ما ورد أعلاه بالنسبة لي.


في حالتي ، لاحظت أن منطق التوجيه كان ينزلق إذا قمت بتعديل $location.hash() . الخدعة التالية عملت ..

$scope.scrollTo = function(id) {
    var old = $location.hash();
    $location.hash(id);
    $anchorScroll();
    //reset to old to keep any additional routing logic from kicking in
    $location.hash(old);
};

في رأيي أنslugslog قد فعلت ذلك ، لكنني سأغير شيئًا واحدًا. سأستخدم استبدال بدلاً من ذلك حتى لا تضطر إلى ضبطه.

$scope.scrollTo = function(id) {
    var old = $location.hash();
    $location.hash(id).replace();
    $anchorScroll();
};

البحث عن Docs "طريقة الاستبدال"


قد يكون هذا سمة جديدة لـ ngView ، لكنني تمكنت من الحصول على ارتباطات تجزئة مرساة للعمل مع angular-route باستخدام ngView autoscroll و "التجزئة المزدوجة".

ngView (انظر autoscroll)

(تم استخدام الرمز التالي مع حزام الزاوي)

<!-- use the autoscroll attribute to scroll to hash on $viewContentLoaded -->    
<div ng-view="" autoscroll></div>

<!-- A.href link for bs-scrollspy from angular-strap -->
<!-- A.ngHref for autoscroll on current route without a location change -->
<ul class="nav bs-sidenav">
  <li data-target="#main-html5"><a href="#main-html5" ng-href="##main-html5">HTML5</a></li>
  <li data-target="#main-angular"><a href="#main-angular" ng-href="##main-angular" >Angular</a></li>
  <li data-target="#main-karma"><a href="#main-karma" ng-href="##main-karma">Karma</a></li>
</ul>

كان الحل الخاص بي مع ng-route هو هذا التوجيه البسيط:

   app.directive('scrollto',
       function ($anchorScroll,$location) {
            return {
                link: function (scope, element, attrs) {
                    element.click(function (e) {
                        e.preventDefault();
                        $location.hash(attrs["scrollto"]);
                        $anchorScroll();
                    });
                }
            };
    })

تبدو html مثل:

<a href="" scrollTo="yourid">link</a>

كنت أحاول أن أجعل تطبيق Angular مررًا إلى مرسى تحميل opon وركض في قواعد إعادة كتابة عنوان URL لـ $ routeProvider.

بعد تجربة طويلة استقرت على هذا:

  1. تسجيل معالج الأحداث document.onload من قسم .run () في وحدة التطبيق الزاوي.
  2. في معالج معرفة ما كان من المفترض أن العلامة الأصلية كان من المفترض أن يكون عن طريق القيام ببعض العمليات سلسلة.
  3. تجاوز location.hash مع علامة الربط التي تم تجريدها (والتي تتسبب في تعيين $ route على الفور فوقها مرة أخرى باستخدام قاعدة "# /". ولكن هذا أمر جيد ، لأن Angular متزامن الآن مع ما يجري في عنوان URL 4) $ anchorScroll ().

angular.module("bla",[]).}])
.run(function($location, $anchorScroll){
         $(document).ready(function() {
	 if(location.hash && location.hash.length>=1)    		{
			var path = location.hash;
			var potentialAnchor = path.substring(path.lastIndexOf("/")+1);
			if ($("#" + potentialAnchor).length > 0) {   // make sure this hashtag exists in the doc.                          
			    location.hash = potentialAnchor;
			    $anchorScroll();
			}
		}	 
 });


كنت تبحث عن $anchorScroll() .

$anchorScroll()

وهنا المصدر.

بشكل أساسي ، قم فقط بحقنها واستدعائها في وحدة التحكم الخاصة بك ، وسوف يتم تمريرك إلى أي عنصر باستخدام المعرف الموجود في $location.hash()

app.controller('TestCtrl', function($scope, $location, $anchorScroll) {
   $scope.scrollTo = function(id) {
      $location.hash(id);
      $anchorScroll();
   }
});

<a ng-click="scrollTo('foo')">Foo</a>

<div id="foo">Here you are</div>

هنا هو أداة للتظاهر

تعديل: لاستخدام هذا مع التوجيه

قم بإعداد التوجيه الزاوي كالمعتاد ، ثم قم بإضافة التعليمة البرمجية التالية.

app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
  //when the route is changed scroll to the proper element.
  $rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
    $location.hash($routeParams.scrollTo);
    $anchorScroll();  
  });
});

وسيبدو الرابط الخاص بك مثل هذا:

<a href="#/test?scrollTo=foo">Test/Foo</a>

هنا يظهر Plunker التمرير مع التوجيه و $ anchorScroll

وحتى أبسط:

app.run(function($rootScope, $location, $anchorScroll) {
  //when the route is changed scroll to the proper element.
  $rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
    if($location.hash()) $anchorScroll();  
  });
});

وسيبدو الرابط الخاص بك مثل هذا:

<a href="#/test#foo">Test/Foo</a>

لست متأكداً 100٪ إذا كان هذا يعمل طوال الوقت ، ولكن في طلبي هذا يعطيني السلوك المتوقع.

دعنا نقول أنك في صفحة ABOUT ولديك الطريق التالي:

yourApp.config(['$routeProvider', 
    function($routeProvider) {
        $routeProvider.
            when('/about', {
                templateUrl: 'about.html',
                controller: 'AboutCtrl'
            }).
            otherwise({
                redirectTo: '/'
            });
        }
]);

الآن ، في HTML لك

<ul>
    <li><a href="#/about#tab1">First Part</a></li>
    <li><a href="#/about#tab2">Second Part</a></li>
    <li><a href="#/about#tab3">Third Part</a></li>                      
</ul>

<div id="tab1">1</div>
<div id="tab2">2</div>
<div id="tab3">3</div>

فى الختام

بما في ذلك اسم الصفحة قبل المرساة لم خدعة بالنسبة لي. اسمحوا لي أن أعرف عن أفكارك.

الجانب السلبي

سيؤدي ذلك إلى إعادة عرض الصفحة ثم الانتقال إلى نقطة الارتساء.

تحديث

أفضل طريقة لإضافة ما يلي:

<a href="#tab1" onclick="return false;">First Part</a>

ليست هناك حاجة لتغيير أي توجيه أو أي شيء آخر يحتاج فقط إلى استخدام target="_self" عند إنشاء الروابط

مثال:

<a href="#faq-1" target="_self">Question 1</a>
<a href="#faq-2" target="_self">Question 2</a>
<a href="#faq-3" target="_self">Question 3</a>

واستخدم سمة id في عناصر html مثل هذا:

<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="faq-3">Question 3</h3>

ليست هناك حاجة لاستخدام ## كما أشار / المذكورة في التعليقات ؛-)


هنا نوع من الحل البديل dirty عن طريق إنشاء توجيه مخصص سيتم التمرير إلى عنصر محدد (مع "faq" hardcoded)

app.directive('h3', function($routeParams) {
  return {
    restrict: 'E',
    link: function(scope, element, attrs){        
        if ('faq'+$routeParams.v == attrs.id) {
          setTimeout(function() {
             window.scrollTo(0, element[0].offsetTop);
          },1);        
        }
    }
  };
});

http://plnkr.co/edit/Po37JFeP5IsNoz5ZycFs?p=preview


يمكنك محاولة استخدام anchorScroll .

Example

لذا سيكون جهاز التحكم:

app.controller('MainCtrl', function($scope, $location, $anchorScroll, $routeParams) {
  $scope.scrollTo = function(id) {
     $location.hash(id);
     $anchorScroll();
  }
});

والرأي:

<a href="" ng-click="scrollTo('foo')">Scroll to #foo</a>

... وليس سرا لمعرف المرساة:

<div id="foo">
  This is #foo
</div>

$anchorScroll يعمل على هذا ، ولكن هناك طريقة أفضل بكثير لاستخدامه في الإصدارات الأحدث من Angular.

الآن ، يقبل $anchorScroll التجزئة كوسيطة اختيارية ، لذا لن تضطر إلى تغيير $location.hash على الإطلاق. ( $anchorScroll() )

هذا هو الحل الأفضل لأنه لا يؤثر على الطريق على الإطلاق. لم أستطع الحصول على أي من الحلول الأخرى للعمل لأنني أستخدم ngRoute وسيتم إعادة تحميل المسار بمجرد تعيين $location.hash(id) ، قبل أن $anchorScroll القيام بسحره.

إليك كيفية استخدامه ... أولاً ، في التوجيه أو وحدة التحكم:

$scope.scrollTo = function (id) {
  $anchorScroll(id);  
}

ثم في العرض:

<a href="" ng-click="scrollTo(id)">Text</a>

أيضًا ، إذا كنت بحاجة إلى حساب شريط تنقل ثابت (أو واجهة مستخدم أخرى) ، فيمكنك تعيين الإزاحة لـ $ anchorScroll مثل هذا (في وظيفة تشغيل الوحدة النمطية الرئيسية):

.run(function ($anchorScroll) {
   //this will make anchorScroll scroll to the div minus 50px
   $anchorScroll.yOffset = 50;
});

<a href="##faq-1">Question 1</a>
<a href="##faq-2">Question 2</a>
<a href="##faq-3">Question 3</a>

<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="faq-3">Question 3</h3>




hashtag