【问题标题】:AngularJS: Auto-scroll to anchor point after state changeAngularJS:状态更改后自动滚动到锚点
【发布时间】:2015-10-15 17:13:52
【问题描述】:

我希望用户点击页面上的链接,这将触发 stateChange 并引导他们进入新状态。我想要实现的是当状态完成加载它然后滚动到由上一页上的链接指定的页面上的锚点。

为此,我使用了通过 ui-sref 传递 $stateParam 的组合,如下所示:

<a ui-sref="stateParent.stateChild({id: 'practiceParam'})">goToPage</a>

然后,当到达页面时,上面有一个 div,并附加了一个在 $viewContentLoaded 上激活的指令,因此 DOM 被渲染,我可以搜索一个 ID。 HTML div 看起来像这样:

<div scroll-after-load ></div>

我的滚动指令如下:

angular.module( 'app' ).directive('scrollAfterLoad', function() {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs, $stateParams) {
        scope.$on('$viewContentLoaded', function() {
            console.log('scrollAfterLoad Directive Loaded, $stateParams are: ', $stateParams );
            var idToScroll = attrs.href;
            var $target;
            if (idToScroll) {
                $target = $(idToScroll);
                // the -50 accounts for the top navbar which is fixed on the page and removed from pageflow
                $("html,body").animate({scrollTop: $target.offset().top - 50}, "slow");
            }
        });
    }
  };
});

我还没有在 div 上设置 href,因为我无法访问传递的参数,是我访问不正确吗?我也尝试使用更标准的 state.go() 来传递 stateParam,但我的结果仍然为空。

一旦我可以传递一个 stateparam,我的想法就是向注入到新加载页面上的 div 的参数添加一个 href,并自动滚动到该页面上的另一个 div,其 ID 与我传递的参数匹配。

另外,在我的 ui-view 上,我将 autoscroll 设置为 true,因此页面会自动加载到顶部,我喜欢这种行为,这就是我需要在 scoll 激活之前完成加载的状态的原因。

【问题讨论】:

  • 有趣的解决方案,但我宁愿远离我项目中的更多依赖项并为它编写一个简单的指令。

标签: angularjs angular-ui-router autoscroll


【解决方案1】:

您的问题是您试图将$stateParams 服务注入到链接函数中。但是,这种注入的正确位置是在工厂方法,即指令的定义处。工厂方法在模块中注册 - 就像您使用 scrollAfterLoad 指令一样。更多信息请查看AngularJS Dependency Injection

回到您的问题:如果您实际上将$stateParams 注入指令的工厂方法中,则意味着在顶部您将能够轻松访问参数。您的指令可能如下所示:

angular.module( 'app' ).directive('scrollAfterLoad', ['$stateParams', function($stateParams) {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs) {
        scope.$on('$viewContentLoaded', function() {
            console.log('scrollAfterLoad Directive Loaded, $stateParams are: ', $stateParams );
            var idToScroll = attrs.href;
            var $target;
            if (idToScroll) {
                $target = $(idToScroll);
                // the -50 accounts for the top navbar which is fixed on the page and removed from pageflow
                $("html,body").animate({scrollTop: $target.offset().top - 50}, "slow");
            }
        });
    }
  };
}]);

请注意,我已从您的链接函数中删除了 $stateParams 并将其放在顶部。这样,该服务将在链接函数中可用 - 实际上在整个指令中。

我在Plunker 中复制了你的场景。

【讨论】:

  • 我明白了,这是有道理的,而且我的项目中的参数正在工作。非常感谢你的帮忙!希望我只是把东西放在错误的地方或不正确地访问参数。
【解决方案2】:

使用angular-scroll,您可以这样做:

scroll target id 作为状态参数传递给子状态控制器,然后滚动到带有scrollToAnimated(element) 的元素。

如果您想让它可重复使用,您可以创建该控制器的工厂并将其注入子状态的解析中。这应该也可以,但我还没有测试过。

如果您处于子状态,您可能需要重新触发滚动并再次单击状态更改链接。这就是为什么我添加了 checkState 方法,如果我们处于子状态以重复滚动,它会重新加载当前状态。

请看下面的演示或fiddle

我认为您的指令不起作用,因为您没有将 href 属性传递给您的指令。

您可以通过将href="targetId" 传递给您的指令来解决此问题,其中在您的子控制器中添加了targetId$scope.targetId = $stateParams.id。或者,如果您不使用隔离作用域,则可以直接访问 $scopetargetId

无论如何,我都会像在演示中那样做,或者在内部解决工厂时这样做。

angular.module('demoApp', ['ui.router', 'duScroll'])
	.controller('MainControlller', MainController)
	.config(Config);

function MainController($scope, $state) {
	$scope.checkState = function() {
    	//console.log($state.current);
        if($state.current.name == 'parent.child') {
            //console.log('parent.child state');
        	// reload to retrigger scrolling again
           $state.reload();
        }
    };
}

function Config($urlRouterProvider, $stateProvider) {
	$urlRouterProvider.otherwise('/');
    
    $stateProvider
    	.state('parent', {
        	url: '/',
        	templateUrl: 'home.html'
    })
    	.state('parent.child', {
    	url: 'child/:id',
        templateUrl: 'child.html',
        controller: function($scope, $stateParams, $document) {
        	var scrollElement = angular
                .element(document.getElementById($stateParams.id));
            console.log(scrollElement);
            $document.scrollToElementAnimated(scrollElement);
        }
    });
               
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-scroll/0.7.3/angular-scroll.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<div ng-app="demoApp" ng-controller="MainController">
    <script type="text/ng-template" id="home.html">
        <a ui-sref="parent.child({id: 'practiceParam'})" ng-click="checkState()">go to practice</a>
        <div ui-view=""></div>
    </script>
    <script type="text/ng-template" id="child.html">
        <!--<a href="#practiceParam" du-smooth-scroll="">scroll to practice</a>
        --><p>
            Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
        </p><p>
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
        </p><p>
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>
<p>
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
        </p>
        <p>
            Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
        </p>
        <h1 id="practiceParam">practice</h1>
        <p>
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
        </p><p>
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</p>
<p>
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
        </p>
        <a ui-sref="parent">back</a>
    </script>
    
    <div ui-view=""></div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 2015-12-31
    • 2023-04-10
    • 1970-01-01
    • 2017-11-10
    相关资源
    最近更新 更多