Programing

AngularJS에서 앵커 해시 링크를 처리하는 방법

lottogame 2020. 3. 8. 09:53
반응형

AngularJS에서 앵커 해시 링크를 처리하는 방법


AngularJS 에서 앵커 해시 링크를 잘 처리하는 방법을 아는 사람이 있습니까?

간단한 FAQ 페이지에 대한 다음 마크 업이 있습니다.

<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 +를 지원해야하므로 허용되는 해결책이 아니라고 두려워합니다.


찾고 있습니다 $anchorScroll().

다음은 (크 래피) 설명서입니다.

그리고 여기 소스가 있습니다.

기본적으로 컨트롤러에 주입하고 호출하면 ID가있는 모든 요소로 스크롤됩니다. $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>

다음은 라우팅과 $ anchorScroll을 사용한 스크롤을 보여주는 Plunker입니다.

그리고 더 간단합니다.

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>

필자의 경우을 수정하면 라우팅 논리가 시작되고 있음을 알았습니다 $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);
};

라우팅을 변경할 필요가 없으며 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>

그리고 다음과 같이 html 요소 id속성을 사용하십시오 .

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

주석에서 지적 / 언급 된대로 # #을 사용할 필요가 없습니다 ;-)


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

항상 경로를 알고 있다면 다음과 같이 앵커를 추가하면됩니다.

href="#/route#anchorID

여기서 route현재 각 경로이며 anchorID일치하는 <a id="anchorID">페이지에 어딘가에


이것은 DOM을 다루기 때문에 더 Angular-y 인 지시문을 사용하는 솔루션이었습니다.

여기 Plnkr

깃 허브

암호

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-switch에 연결되어 있고 새로 고침이 앱을 본질적으로 손상시킬 수 있기 때문에 이것은 나를 위해 일했습니다.


$anchorScroll 이를 위해 작동하지만 최신 버전의 Angular에서 사용하는 훨씬 더 좋은 방법이 있습니다.

이제 $anchorScroll해시를 선택적인 인수로 받아들이므로 전혀 변경할 필요가 없습니다 $location.hash. ( 문서 )

이것은 경로에 전혀 영향을 미치지 않기 때문에 가장 좋은 솔루션입니다. 내가 ngRoute을 사용하고 있기 때문에 작업에 다른 솔루션 중 하나를 얻을 수 있고 경로는 최대한 빨리 설정으로 다시 것 $location.hash(id)이전에, $anchorScroll그 마술을 할 수 있습니다.

지시어 또는 컨트롤러에서 먼저 사용하는 방법은 다음과 같습니다.

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

그리고보기에서 :

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

또한 고정 탐색 메뉴 (또는 다른 UI)를 고려해야하는 경우 다음과 같이 주 모듈의 실행 기능에서 $ anchorScroll의 오프셋을 설정할 수 있습니다.

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

각도 경로에 해시 접두사를 설정하십시오. $locationProvider.hashPrefix('!')

전체 예 :

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

내 앱의 경로 논리 에서이 문제를 해결했습니다.

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

이것은 오래된 게시물이지만 다양한 솔루션을 연구하는 데 오랜 시간을 보냈으므로 더 간단한 것을 공유하고 싶었습니다. 태그에 추가 target="_self"하면 문제가 <a>해결되었습니다. 링크가 작동하여 페이지의 올바른 위치로 이동합니다.

그러나 Angular는 여전히 URL에서 #에 약간의 이상한 점을 삽입 하므로이 방법을 사용한 후 탐색을 위해 뒤로 버튼을 사용하는 데 문제가 발생할 수 있습니다.


이것은 ngView의 새로운 속성 일지 모르지만 속성과 'double-hashes' 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>

나는 이렇게 할 수있다 :

<li>
<a href="#/#about">About</a>
</li>

다음은 지정된 요소 (하드 코드 된 "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


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

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>

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>

앵커 ID에 대한 비밀은 없습니다.

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

Angular 앱을 앵커 opon로드로 스크롤하고 $ routeProvider의 URL 다시 쓰기 규칙을 실행하려고했습니다.

오랜 실험 끝에 나는 이것에 정착했다.

  1. Angular 앱 모듈의 .run () 섹션에서 document.onload 이벤트 핸들러를 등록하십시오.
  2. 핸들러에서 일부 문자열 작업을 수행하여 원본에 앵커 태그가 있어야하는 것을 찾으십시오.
  3. $ routeProvider가 "# /"규칙을 사용하여 즉시 다시 덮어 쓰는 앵커 태그로 location.hash를 재정의합니다. 그러나 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();
			}
		}	 
 });


이것이 항상 작동하는지 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>

사용하지 않으려면 ng-click여기에 다른 해결책이 있습니다. filter현재 상태에 따라 올바른 URL을 생성하기 위해 a 사용합니다 . 내 예제는 ui.router 를 사용 합니다 .

이점은 사용자가 링크로 이동하는 위치를 볼 수 있다는 것입니다.

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

필터 :

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

스크롤 기능을 쉽게 사용하십시오. 또한 추가 기능으로 Animated / Smooth 스크롤지원 합니다. 각도 스크롤 라이브러리의 세부 사항 :

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

바우어 :bower install --save angular-scroll

npm :npm install --save angular-scroll

축소 버전-9kb

부드러운 스크롤 (애니메이션 스크롤) -예

스크롤 스파이 -예

문서 -우수

데모-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();
        }
    }
});

경로 변경시 페이지 상단으로 스크롤됩니다.

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

이 코드를 컨트롤러에 넣으십시오.


내 마음에 @slugslog가 있었지만 한 가지를 바꿀 것입니다. 대신 replace를 사용하여 다시 설정할 필요가 없습니다.

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

문서 검색에서 "바꾸기 방법"


위의 해결책 중 어느 것도 나를 위해 작동하지 않지만 방금 시도했지만 효과가있었습니다.

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

따라서 색인 페이지로 시작한 다음 기존 앵커를 사용하도록 페이지에 알리는 것이 필요하다는 것을 깨달았습니다.


때로는 angularjs 응용 프로그램 해시 탐색이 작동하지 않고 부트 스트랩 jquery 자바 스크립트 라이브러리 가이 유형의 탐색을 광범위하게 사용 target="_self"하여 앵커 태그에 추가 되도록 작동합니다 . 예 :<a data-toggle="tab" href="#id_of_div_to_navigate" target="_self">


https://code.angularjs.org/1.4.10/docs/api/ngRoute/provider/ $ routeProvider를 참조 하십시오.

[reloadOnSearch = true]-{boolean =}-$ location.search () 또는 $ location.hash () 만 변경 될 때 경로를 다시로드합니다.

이것을 false로 설정하면 위의 모든 사항없이 트릭을 수행했습니다.


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를 전혀 변경할 필요가 없었습니다.

참고 URL : https://stackoverflow.com/questions/14712223/how-to-handle-anchor-hash-linking-in-angularjs



반응형