【问题标题】:Directive not executing corretcly on route change路线更改时指令未正确执行
【发布时间】:2017-09-13 00:00:46
【问题描述】:

每次用户滚动一点时,我都会在 Angular 中添加固定到顶级类的指令,以获得带有一些基本信息的粘性标题。指令如下:

app.directive('fixedTop', function ($window) {
    var $win = angular.element($window);
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
           $log.debug("fixedTop init");
           var topClass = attrs.fixedTop;
           var containerClass = 'container';
           var offsetTop = element.offset().top;
           $win.on('scroll', function (e) {
                if ($win.scrollTop() >= offsetTop) {
                    element.addClass(topClass);
                    element.children().first().addClass(containerClass);
                    $log.debug("fixedTop add topClass");                        
                } else {
                    element.removeClass(topClass);
                    element.children().first().removeClass(containerClass);
                    $log.debug("fixedTop remove topClass");
                }
            });
        }
    }
});

我的路线是在没有任何自定义插件的情况下定义的:

$routeProvider
        .when('/', {
            templateUrl: 'home.html',
            controller: 'home'
        })
        //rest of routes

索引html:

<div class="row" id="main-ccontent">
    <div class="col-sm-10 col-md-10 col-lg-offset-1 main">
        <div ng-view="" class="container main-container">
        </div>
    </div>
</div>

使用指令的两个模板之一以以下开头:

<div class="row header-fixed animate-appear" fixed-top="fix-to-top">
    <!--      Header       -->
</div>
<div>
    <!-- Content goes here -->
</div>

它应该工作得很好,问题是,每当我更改路线(转到其他子页面)时,我的指令都不起作用,我必须执行页面刷新 (F5) 以使其再次工作。

所以我想它与路由的工作方式以及何时呈现指令或类似的事情有关?

更新:添加日志记录后,在我滚动时首次加载。在控制台日志中:

fixedTop init
(times 6 ) fixedTop remove topClass
(times 38) fixedTop add topClass

但是当我导航到另一条路线时,我有:

fixedTop init
(times 6 ) fixedTop remove topClass
fixedTop add topClass
fixedTop remove topClass
fixedTop add topClass
fixedTop remove topClass
fixedTop add topClass
fixedTop remove topClass
fixedTop add topClass
fixedTop remove topClass
fixedTop add topClass
fixedTop remove topClass

.. 以此类推... 所以看起来像是在改变路线,它正在打开和关闭它

UPDATE 2 添加了 scrollTop 和 offset 调试:

            $log.debug(offsetTop);
            $log.debug($win.scrollTop());

而路线变更结果是

fixedTop init
70
91.81817626953125
fixedTop add topClass
1316.3635711669922
91.81817626953125
fixedTop remove topClass
70
96.36363220214844
fixedTop add topClass
1316.3635711669922
96.36363220214844
fixedTop remove topClass

这仅在路线更改时发生。每当我正常进入页面时,指令都有正确的偏移值

【问题讨论】:

  • 你测试了吗?将 console.log 放入滚动监听函数和初始化函数中。看看 Init 函数调用了多少次,onscroll 函数是否正常工作
  • 如果没有minimal reproducible example,很难诊断这个问题,但是由于您的指令引用了'container' 类,但该类似乎不在您显示的 HTML 中,我可能 猜测它在home.html中。当路由发生变化时,该元素将被其他元素替换,并且该指令不再可操作。
  • @Leguest 我添加了日志记录并更新了我的问题。
  • @Claies 指令已在容器中。由于标题设置为位置:固定,它需要额外的容器来对齐内容。一切正常,直到模板随路线改变。更新了原始问题的结构
  • 这似乎与您的 if 逻辑有关,您需要检查 console.log offsetTop 和 $win.scrollTop()

标签: angularjs


【解决方案1】:

过了一会儿,我又回到了这个。 根本原因是 ng-route 上的更改内容是动态的,并且

element.offset().top

重新渲染元素时值错误。 根据https://stackoverflow.com/a/30380846/1254412 的回答修复我 ,详细解释为什么我原来的方法是错误的

如果元素被包装在空 div 中并使用以下代码,则最终指令现在正在工作

app.directive('fixedTop', function ($window, $log) {
var $win = angular.element($window);
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        var topClass = attrs.fixedTop;
        var containerClass = 'container';
        var parent = element.parent();
        $win.on('scroll', function (e) {
            var offsetTop = parent.offset().top;
            if ($win.scrollTop() >= offsetTop) {
                element.addClass(topClass);
                element.children().first().addClass(containerClass);
                parent.height(element.height());
            } else {
                element.removeClass(topClass);
                element.children().first().removeClass(containerClass);
                parent.css("height", null);
            }
          });
        }
    }
});

用法:

<div>
    <div class="row header-fixed animate-appear" fixed-top="fix-to-top">
    <!--  contents -->
    </div>
<div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多