วิธีจัดการกับการเชื่อมโยงแฮช Anchor ใน AngularJS


318

คุณใด ๆ รู้วิธีจัดการการเชื่อมโยงแฮ็กสมอใน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 /: ตอน " และในการตรวจสอบตัวควบคุมที่เกี่ยวข้อง$routeParams.chapterหลังจากองค์ประกอบที่ตรงกันแล้วใช้ jQuery เพื่อเลื่อนลงไป

แต่แล้ว AngularJS ก็มาหาฉันอีกแล้วเลื่อนไปที่ด้านบนของหน้า

ดังนั้นทุกคนที่นี่ทำสิ่งที่คล้ายกันในอดีตและรู้วิธีแก้ปัญหาที่ดีหรือไม่

แก้ไข: การเปลี่ยนเป็น html5Mode ควรแก้ปัญหาของฉัน แต่เราต้องรองรับ IE8 + ต่อไปดังนั้นฉันจึงกลัวว่าไม่ใช่วิธีแก้ปัญหาที่ยอมรับ: /


ฉันคิดว่าเชิงมุมแนะนำให้ใช้ng-href=""แทน
piggyback

10
ฉันคิดว่า ng-href ใช้ได้เฉพาะในกรณีที่ url มีข้อมูลแบบไดนามิกที่จำเป็นต้องเชื่อมโยงกับแบบจำลอง ng ฉันสงสัยว่าคุณกำหนด hashPrefix ให้กับ locationProvider หรือไม่ถ้าหากมันจะเพิกเฉยต่อลิงค์ไปยัง ID ของ: docs.angularjs.org/guide/dev_guide.services.$location
Adam

อดัมถูกต้องเกี่ยวกับการใช้ ng-href
Rasmus


นี่เป็นปัญหาสำหรับ Angular ใหม่: stackoverflow.com/questions/36101756/…
phil294

คำตอบ:


375

$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>

5
ปัญหาอาจเกิดขึ้นได้เมื่อคุณเพิ่มการเราต์: ถ้าเพิ่ม ngView การเปลี่ยนแปลงแต่ละครั้งของแฮชจะทริกเกอร์การโหลดเส้นทางใหม่ ... ในตัวอย่างของคุณไม่มีการกำหนดเส้นทางและ url ไม่ได้สะท้อนรายการปัจจุบัน ... แต่ขอบคุณที่ชี้ไปที่ $ anchorScroll
Valentyn Shybanov

1
@blesh การเรียก location.hash (X) จะเปลี่ยนหน้าเนื่องจากการกำหนดเส้นทางจะควบคุมมุมมอง
dsldsl

24
โซลูชันนี้ทำให้แอปพลิเคชันทั้งหมดของฉันแสดงผลอีกครั้ง

2
@dsldsl && @OliverJosephAsh: $ location.hash () จะไม่โหลดหน้าซ้ำ ถ้าเป็นเช่นนั้นจะมีสิ่งอื่นเกิดขึ้น นี่คือเสียงอึกทึกเดียวกันกับเวลาที่เขียนออกมาขณะที่หน้ากำลังโหลดคุณจะเห็นว่ามันไม่เปลี่ยนแปลง หากคุณต้องการเลื่อนไปที่จุดยึดแท็กในหน้าปัจจุบันโดยไม่ต้องโหลดเส้นทางใหม่ <a href="#foo">foo</a>การเชื่อมโยงปกติ ตัวอย่างรหัสของฉันคือการแสดงการเลื่อนไปยัง id ในการเปลี่ยนเส้นทาง
เบ็นเลช

4
@blesh: ฉันขอแนะนำให้คุณลบแฮชหลังจากเลื่อนไปยังส่วนที่ต้องการด้วยวิธีนี้ URL ไม่ได้ปนเปื้อนกับเนื้อหาที่ไม่ควรมี ใช้สิ่งนี้: $location.search('scrollTo', null)
kumarharsh

168

$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);
};

5
ขอบคุณที่ยอดเยี่ยมสำหรับเหตุผลการกำหนดเส้นทางตรรกะปฏิเสธอย่างแน่นอนแม้จะใช้โซลูชัน. run (... ) ของ @ blesh และนี่เป็นการเรียงลำดับ
ljs

8
เคล็ดลับ "การประหยัดค่าแฮชเก่า" ของคุณนั้นเป็นเครื่องช่วยชีวิตแน่นอน มันช่วยป้องกันการโหลดหน้าซ้ำในขณะที่รักษาเส้นทางให้สะอาด ความคิดที่ยอดเยี่ยม!
ThisLanham

2
ทำได้ดีนี่. แต่หลังจากใช้งานโซลูชันของคุณแล้ว URL จะไม่อัปเดตค่าของรหัสเป้าหมาย
Mohamed Hussain

1
ฉันมีประสบการณ์เช่นเดียวกับโมฮาเหม็ด ... มันหยุดการโหลดซ้ำ แต่มันแสดงเส้นทางที่ไม่มี hashless (และ $ anchorScroll ไม่มีผล) 1.2.6 Hmmmm
ไมเคิล

3
$location.hash(my_id); $anchorScroll; $location.hash(null)ฉันใช้ มันป้องกันการโหลดซ้ำและฉันไม่ต้องจัดการกับoldตัวแปร
MFB

53

ไม่จำเป็นต้องเปลี่ยนเส้นทางหรือสิ่งอื่นใดเพียงแค่ต้องใช้ 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>

ไม่จำเป็นต้องใช้ ## ตามที่แหลม / กล่าวถึงในความคิดเห็น ;-)


1
สิ่งนี้ไม่ได้ผลสำหรับฉัน แต่วิธีแก้ปัญหาที่นี่ทำได้: stackoverflow.com/a/19367249/633107
Splaktar

6
ขอบคุณสำหรับการแก้ปัญหานี้ แต่เป้าหมาย = "_ self" ก็เพียงพอแล้ว ไม่จำเป็นต้องเพิ่ม #
Christophe P

5
target = "_ self" เป็นคำตอบที่ดีที่สุดอย่างแน่นอน (ไม่จำเป็นต้องเพิ่ม double # ตามที่ Christophe P ระบุไว้) สิ่งนี้ใช้ได้ไม่ว่า Html5Mode จะเปิดหรือปิดก็ตาม
นิวแมน

3
ง่ายและสมบูรณ์ ทำงานให้ฉันโดยไม่จำเป็นต้องเพิ่มการพึ่งพามุมอื่น
adeady

4
นี่คือทางออกที่ถูกต้อง ไม่จำเป็นต้องเกี่ยวข้องกับบริการ $ anchorScroll เชิงมุม ดูเอกสารสำหรับแท็ก: https://developer.mozilla.org/en/docs/Web/HTML/Element/a
Yiling

41
<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>

! น่ากลัว ไกลโดยวิธีที่ง่ายที่สุด แต่ความคิดวิธีการเชื่อมโยงไปยังจุดยึดในหน้าแยก? (เช่น / ผลิตภัณฑ์ # หนังสือ)
8bithero

ฉันคิดว่ามันเป็นเช่นเดียวกับการแก้ปัญหา (/ หนังสือ ## ผลิตภัณฑ์) ใน AngularJS
lincolnge

1
จากประสบการณ์ของฉัน href = "##" ใช้ได้เฉพาะเมื่อมีการฉีด $ anchorScroll
Brian Park

9
ดูเหมือนว่าจะค่อนข้างง่าย แต่ไม่ทำงาน :-(
brykneval

4
ฉันเพิ่ม target = "_ self" และใช้งานได้อย่างมีเสน่ห์สำหรับการนำทางทุกประเภทภายในหน้าเว็บ (อ่านแถบเลื่อนไปยังส่วนต่างๆและอื่น ๆ ) ขอบคุณสำหรับการแบ่งปันเคล็ดลับที่ดีและง่ายที่สุดนี้
Kumar Nitesh

19

หากคุณรู้เส้นทางเสมอคุณสามารถต่อท้ายจุดยึดได้ดังนี้

href="#/route#anchorID

ที่routeเป็นเส้นทางเชิงมุมปัจจุบันและanchorIDตรงกับ<a id="anchorID">ที่ใดที่หนึ่งบนหน้าเว็บ


1
สิ่งนี้ทริกเกอร์การเปลี่ยนเส้นทางตามปกติของ AngularJS และทำให้หมดกำลังใจ ในกรณีของฉันมันเห็นได้ชัดตั้งแต่วิดีโอ YouTube ในหน้าคำถามที่พบบ่อย / ช่วยเหลือโหลดใหม่
Robin Andersson

9
@ RobinWassén-Andersson โดยการระบุreloadOnSearch: falseเส้นทางนั้นในการกำหนดค่าเส้นทางของคุณเชิงมุมจะไม่ทริกเกอร์การเปลี่ยนเส้นทางและจะเลื่อนไปที่ id เมื่อใช้ร่วมกับเส้นทางทั้งหมดที่ระบุในaแท็กฉันจะบอกว่านี่เป็นทางออกที่ง่ายที่สุดและตรงไปตรงมาที่สุด
Elise

ขอบคุณ. สิ่งนี้ช่วยฉัน ฉันไม่ได้ใช้เส้นทางที่กำหนดเองในแอปดังนั้น href = "# / # anchor-name" จึงใช้งานได้ดีมาก!
Jordan

14

$anchorScroll ใช้งานได้ แต่มีวิธีที่ดีกว่ามากในการใช้กับ Angular รุ่นใหม่กว่า

ตอนนี้$anchorScrollยอมรับการแฮชเป็นอาร์กิวเมนต์ที่เป็นตัวเลือกดังนั้นคุณไม่จำเป็นต้องเปลี่ยน$location.hashเลย ( เอกสาร )

นี่เป็นทางออกที่ดีที่สุดเพราะไม่กระทบเส้นทางเลย ฉันไม่สามารถแก้ไขปัญหาอื่น ๆ ให้ทำงานได้เพราะฉันใช้ ngRoute และเส้นทางจะโหลดใหม่ทันทีที่ฉันตั้งค่า$location.hash(id)ก่อนที่จะ$anchorScrollสามารถใช้เวทมนตร์

นี่คือวิธีการใช้งาน ... อันดับแรกในคำสั่งหรือตัวควบคุม:

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

แล้วในมุมมอง:

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

นอกจากนี้หากคุณต้องการบัญชี navbar คงที่ (หรือ UI อื่น ๆ ) คุณสามารถตั้งค่าออฟเซ็ตสำหรับ $ anchorScroll เช่นนี้ (ในฟังก์ชั่นการทำงานของโมดูลหลัก):

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

ขอบคุณ คุณจะใช้กลยุทธ์สำหรับลิงก์แฮชรวมกับการเปลี่ยนเส้นทางได้อย่างไร ตัวอย่าง: คลิกรายการการนำทางนี้ซึ่งเปิดมุมมองที่แตกต่างกันและเลื่อนลงไปยังidมุมมองที่เฉพาะเจาะจง
Kyle Vassella

ลองไปรบกวน ... ถ้าคุณมีโอกาสคุณจะให้คำถามสแต็คของฉันได้อย่างรวดเร็ว? ฉันรู้สึกว่าคำตอบของคุณที่นี่ทำให้ฉันสนิท แต่ฉันก็ไม่สามารถนำไปใช้ได้เลย: stackoverflow.com/questions/41494330/… . ฉันก็กำลังใช้ngRouteและรุ่นที่ใหม่กว่าของ Angular
Kyle Vassella

ฉันขอโทษที่ฉันยังไม่ได้ลองกรณีนั้น ... แต่คุณลองดู$ location.search ()หรือ$ routeParamsหรือยัง บางทีคุณอาจใช้อย่างใดอย่างหนึ่งในการเริ่มต้นของตัวควบคุมของคุณ - ถ้า scrollTo ของคุณค้นหาพารามิเตอร์อยู่ใน URL จากนั้นตัวควบคุมสามารถใช้ $ anchorScroll เป็นด้านบนเพื่อเลื่อนหน้า
รีเบคก้า

2
โดยการส่งรหัสโดยตรงไปที่ $ anchorScroll เส้นทางของฉันเปลี่ยนจากสิ่งที่ต้องการ / contact # contact เป็น just / contact นี่ควรเป็นคำตอบที่ยอมรับได้
RandomUs1r

12

นี่เป็นวิธีแก้ปัญหาของฉันโดยใช้คำสั่งซึ่งดูเหมือน Angular-y มากกว่าเพราะเรากำลังจัดการกับ DOM:

โปรดไปที่นี่

GitHub

รหัส

angular.module('app', [])
.directive('scrollTo', function ($location, $anchorScroll) {
  return function(scope, element, attrs) {

    element.bind('click', function(event) {
        event.stopPropagation();
        var off = scope.$on('$locationChangeStart', function(ev) {
            off();
            ev.preventDefault();
        });
        var location = attrs.scrollTo;
        $location.hash(location);
        $anchorScroll();
    });

  };
});

HTML

<ul>
  <li><a href="" scroll-to="section1">Section 1</a></li>
  <li><a href="" scroll-to="section2">Section 2</a></li>
</ul>

<h1 id="section1">Hi, I'm section 1</h1>
<p>
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. 
 Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. 
Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium. 
Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
</p>

<h1 id="section2">I'm totally section 2</h1>
<p>
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. 
 Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. 
Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium. 
Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
</p>

ฉันใช้บริการ $ anchorScroll หากต้องการต่อต้านการรีเฟรชหน้าเว็บที่ไปพร้อมกับการเปลี่ยนแฮชฉันไปข้างหน้าและยกเลิกเหตุการณ์ locationChangeStart สิ่งนี้ใช้ได้ผลสำหรับฉันเพราะฉันมีหน้าความช่วยเหลือเชื่อมต่อกับสวิตช์ ng และการรีเฟรชจะทำให้แอปหยุดทำงาน


ฉันชอบแนวทางแก้ไขของคุณ อย่างไรก็ตามคุณจะทำอย่างไรคุณต้องการโหลดหน้าอื่นและเลื่อนไปยังตำแหน่งจุดยึดในเวลาเดียวกัน หากไม่มีเชิงมุมจะเรียกว่า href = "location # hash" แต่คำสั่งของคุณป้องกันการโหลดหน้าเว็บซ้ำ
CMCDragonkai

@CMCDragonkai ด้วยคำสั่งของฉันฉันไม่แน่ใจเพราะฉันใช้ประโยชน์จากการเรียก $ anchorScroll ซึ่งดูเหมือนว่าจะจัดการเลื่อนไปยังองค์ประกอบที่อยู่ในหน้าเท่านั้น คุณอาจต้องยุ่งกับ$ locationหรือ$ windowเพื่อรับบางสิ่งที่เกี่ยวข้องกับการเปลี่ยนหน้า
KhalilRavanna

2
คุณต้องยกเลิกการ unsubscirbe จากเหตุการณ์ locationChangeStart: var off = scope $ on ('$ locationChangeStart', ฟังก์ชัน (ev) {off (); ev.preventDefault ();});

ดีจับ @EugeneTskhovrebov ฉันไปข้างหน้าและเพิ่มคำตอบในการแก้ไข
KhalilRavanna

5

ลองตั้งค่าแฮนำหน้าสำหรับเส้นทางเชิงมุม $locationProvider.hashPrefix('!')

ตัวอย่างเต็มรูปแบบ:

angular.module('app', [])
  .config(['$routeProvider', '$locationProvider', 
    function($routeProvider, $locationProvider){
      $routeProvider.when( ... );
      $locationProvider.hashPrefix('!');
    }
  ])

สิ่งนี้ไม่ส่งผลกระทบต่อผลลัพธ์ มันจะหวานแม้ว่า
Rasmus

2
คุณแน่ใจไหม. ทำไมมันไม่ทำงาน หากคำนำหน้าแฮชคือ! ดังนั้นการกำหนดเส้นทางแฮชควรเป็น #! ดังนั้น AngularJS ควรตรวจจับเมื่อเป็นเพียง #hash ควรยึดการเลื่อนโดยอัตโนมัติและใช้ได้ทั้ง URL โหมด HTML5 และ URL โหมดแฮช
CMCDragonkai

5

ฉันได้สิ่งนี้ในตรรกะเส้นทางสำหรับแอปของฉัน

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;
      }
    });
}

1
สิ่งนี้ไม่ทำงาน: ข้อผิดพลาด: [$ injector: modulerr] ไม่สามารถสร้างอินสแตนซ์ของมุมโมดูลได้เนื่องจาก: ข้อผิดพลาด: 'ตัวจัดการ' ไม่ถูกต้องในเมื่อ ()
geoidesic

5

นี่คือโพสต์เก่า แต่ฉันใช้เวลานานในการค้นคว้าวิธีแก้ปัญหาต่าง ๆ ดังนั้นฉันต้องการแบ่งปันอีกหนึ่งง่าย ๆ เพียงแค่เพิ่มtarget="_self"ไปยัง<a>แท็กแก้ไขสำหรับฉัน ลิงค์ใช้งานได้และพาฉันไปยังตำแหน่งที่เหมาะสมบนหน้าเว็บ

อย่างไรก็ตาม Angular ยังคงใส่ความแปลกประหลาดด้วย # ใน URL ดังนั้นคุณอาจพบปัญหาในการใช้ปุ่มย้อนกลับสำหรับการนำทางและหลังจากใช้วิธีนี้


4

นี่อาจเป็นแอททริบิวใหม่สำหรับ ngView แต่ฉันสามารถทำให้แอปยึดแฮชลิงก์ให้ทำงานangular-routeโดยใช้ngView autoscrollคุณลักษณะและ 'แฮชสองครั้ง' ได้

ngView (ดูการควบคุมอัตโนมัติ)

(รหัสต่อไปนี้ใช้กับสายรัดเชิงมุม)

<!-- 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>


2

นี่คือวิธีแก้ไขปัญหาสกปรกโดยการสร้างคำสั่งกำหนดเองที่จะเลื่อนไปที่องค์ประกอบที่ระบุ (ด้วย hardcoded "faq")

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


วิธีนี้ใช้งานได้จริง แต่เป็นไปตามที่คุณพูดสกปรก สกปรกมาก. ลองดูว่าคนอื่นจะคิดวิธีแก้ปัญหาที่ดีกว่านี้ได้หรือไม่
Rasmus

Angular มีฟังก์ชั่น scrollTo ในตัว$anchorScrollแล้วดูคำตอบของฉัน
เบ็นเลช

เปลี่ยน plunker ให้สกปรกน้อยลง: ใช้ $ location.path () ดังนั้นจึงไม่มีซอร์สโค้ด "faq" hardcoded และยังพยายามใช้ $ anchorScroll แต่ดูเหมือนว่าเนื่องจากการกำหนดเส้นทางจะไม่ทำงาน ...
Valentyn Shybanov


2

หากคุณไม่ต้องการใช้ng-clickที่นี่เป็นทางเลือกอื่น มันใช้filterเพื่อสร้าง URL ที่ถูกต้องขึ้นอยู่กับสถานะปัจจุบัน ตัวอย่างการใช้งานของฉันui.router

ประโยชน์คือผู้ใช้จะเห็นว่าลิงค์ไปที่ใด

<a href="{{ 'my-element-id' | anchor }}">My element</a>

ตัวกรอง:

.filter('anchor', ['$state', function($state) {
    return function(id) {
        return '/#' + $state.current.url + '#' + id;
    };
}])

2

โซลูชันของฉันกับ 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>

คุณจะไม่ต้องระบุแอตทริบิวต์ชอบscroll-to="yourid"และตั้งชื่อคำสั่งscrollTo(และการเข้าถึงแอตทริบิวต์เป็นattrs["scrollTo"]? นอกจากนี้โดยไม่ต้องรวม jQuery explicite จัดการจะต้องมีการมัดด้วยelement.on('click', function (e) {..}).
Theodros Zelleke

1

คุณอาจจะลองใช้anchorScroll

ตัวอย่าง

ดังนั้นตัวควบคุมจะเป็น:

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>

1

ฉันกำลังพยายามทำให้แอปพลิเคชัน Angular ของฉันเลื่อนไปที่แองเคอเรนโหลดและวิ่งเข้าสู่กฎการเขียน URL ใหม่ของ $ routeProvider

หลังจากการทดลองเป็นเวลานานฉันตัดสินในเรื่องนี้:

  1. ลงทะเบียน document.onload ตัวจัดการเหตุการณ์จากส่วน. run () ของโมดูลแอป Angular
  2. ในตัวจัดการค้นหาสิ่งที่มีแท็กจุดยึดเดิมที่ควรจะเป็นโดยการดำเนินการบางอย่างของสตริง
  3. แทนที่ location.hash ด้วยแท็ก anchor stripped down (ซึ่งทำให้ $ routeProvider แทนที่ทับอีกครั้งทันทีด้วยกฎ "# /" แต่ก็ใช้ได้เนื่องจากการ 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();
			}
		}	 
 });


1

ฉันไม่แน่ใจ 100% ว่าจะใช้งานได้ตลอดเวลาหรือไม่ แต่ในแอปพลิเคชันของฉันสิ่งนี้ทำให้ฉันมีพฤติกรรมที่คาดหวัง

ให้บอกว่าคุณอยู่ในหน้าเกี่ยวกับและคุณมีเส้นทางต่อไปนี้:

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>

สรุปแล้ว

รวมถึงชื่อหน้าก่อนที่จะสมอทำเคล็ดลับสำหรับฉัน แจ้งให้เราทราบเกี่ยวกับความคิดของคุณ

ข้อเสีย

นี่จะแสดงหน้าซ้ำอีกครั้งแล้วเลื่อนไปที่จุดยึด

UPDATE

วิธีที่ดีกว่าคือการเพิ่มสิ่งต่อไปนี้:

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

1

รับคุณสมบัติการเลื่อนของคุณได้อย่างง่ายดาย นอกจากนี้ยังรองรับการเคลื่อนไหวแบบเคลื่อนไหว / การเลื่อนอย่างราบรื่นเป็นคุณสมบัติเพิ่มเติม รายละเอียดสำหรับไลบรารีAngular Scroll :

Github - https://github.com/oblador/angular-scroll

ซุ้มประตู :bower install --save angular-scroll

npm :npm install --save angular-scroll

รุ่น Minfied - เพียง 9kb

การเลื่อนอย่างราบรื่น (การเลื่อนแบบเคลื่อนไหว) - ใช่

เลื่อน Spy - ใช่

เอกสาร - ยอดเยี่ยม

การสาธิต - http://oblador.github.io/angular-scroll/

หวังว่านี่จะช่วยได้


1

จาก @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();
        }
    }
});

0

เมื่อเปลี่ยนเส้นทางมันจะเลื่อนไปที่ด้านบนของหน้า

 $scope.$on('$routeChangeSuccess', function () {
      window.scrollTo(0, 0);
  });

ใส่รหัสนี้ในตัวควบคุมของคุณ


0

ในใจของฉัน @slugslog มี แต่ฉันจะเปลี่ยนสิ่งหนึ่ง ฉันจะใช้แทนที่แทนดังนั้นคุณไม่จำเป็นต้องตั้งค่ากลับมา

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

การค้นหาเอกสารสำหรับ "วิธีการแทนที่"


0

วิธีการแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน แต่ฉันลองทำสิ่งนี้และใช้งานได้

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

ดังนั้นฉันรู้ว่าฉันต้องแจ้งให้หน้าเพื่อเริ่มต้นด้วยหน้าดัชนีแล้วใช้สมอดั้งเดิม


0

บางครั้งใน angularjs นำทางแอพลิเคชันแฮชไม่ได้ทำงานและบูต jQuery JavaScript ห้องสมุดทำให้การใช้งานที่กว้างขวางของประเภทของการนำทางนี้จะทำให้การทำงานเพิ่มtarget="_self"ไปยังแท็กสมอ เช่น<a data-toggle="tab" href="#id_of_div_to_navigate" target="_self">


0

ดูhttps://code.angularjs.org/1.4.10/docs/api/ngRoute/provider/ $ routeProvider

[reloadOnSearch = true] - {boolean =} - โหลดเส้นทางใหม่เมื่อมีการเปลี่ยนแปลงเพียง $ location.search () หรือ $ location.hash ()

การตั้งค่านี้เป็นเท็จได้หลอกลวงโดยไม่ต้องใช้ทั้งหมดข้างต้นสำหรับฉัน


0

ฉันใช้ AngularJS 1.3.15 และดูเหมือนว่าฉันไม่ต้องทำอะไรเป็นพิเศษ

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

ดังนั้นสิ่งต่อไปนี้ใช้ได้กับฉันใน html ของฉัน:

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

ฉันไม่จำเป็นต้องทำการเปลี่ยนแปลงใด ๆ กับคอนโทรลเลอร์หรือ JavaScript เลย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.