将类切换绑定到窗口滚动事件

Stu*_*tuR 60 angularjs angularjs-directive

当用户将浏览器窗口滚动到某个点以下时,我正在切换#page div的类.

到目前为止我所做的工作正常:

http://jsfiddle.net/eTTZj/29/

<div ng-app="myApp" scroll id="page">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 element.addClass('min');
                 console.log('Scrolled below header.');
             } else {
                 element.removeClass('min');
                 console.log('Header is in view.');
             }
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

(当他们在标题下方滚动窗口时,100px,该类被切换)

虽然,如果我错了,请纠正我,我觉得这不是用Angular做这件事的正确方法.

相反,我认为执行此操作的最佳方法是使用ng-class并在范围中存储布尔值.像这样的东西:

<div ng-app="myApp" scroll id="page" ng-class="{min: boolChangeClass}">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 scope.boolChangeClass = true;
                 console.log('Scrolled below header.');
             } else {
                 scope.boolChangeClass = false;
                 console.log('Header is in view.');
             }
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

虽然这不是动态的,但如果我在滚动回调中更改scope.boolChangeClass的值,则ng-class不会更新.

所以我的问题是:当用户滚动到特定点以下时,如何最好使用AngularJS切换#page类?

Stu*_*tuR 86

感谢Flek在评论中回答我的问题:

http://jsfiddle.net/eTTZj/30/

<div ng-app="myApp" scroll id="page" ng-class="{min:boolChangeClass}">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 scope.boolChangeClass = true;
             } else {
                 scope.boolChangeClass = false;
             }
            scope.$apply();
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

  • 我非常建议AGAINST`范围.$ apply()`!它会导致每个滚动事件的整页重新评估.在我的情况下,我在顶部菜单获得固定样式时更改图像(几乎是谷歌+正在做的事情).所以我通过javascript手动设置它:`logoelem.css('background-image','url('+ scope.imageLogo +')');`.当我使用scope.$ apply()时,它重新计算页面上的每个`{{showMessage()}}`样式变量.我正在使用一张桌子,因此每次滚动事件都会导致大约40次重新计算.这是滞后的.更新所需的元素只能为我节省许多cpu周期. (8认同)
  • 如果state可以简化为:scope.boolChangeClass = this.pageYOffset> = 100; (5认同)

use*_*066 23

为什么你们都建议重型作业?我不明白为什么这不是一个"有角度"的解决方案:

.directive('changeClassOnScroll', function ($window) {
  return {
    restrict: 'A',
    scope: {
        offset: "@",
        scrollClass: "@"
    },
    link: function(scope, element) {
        angular.element($window).bind("scroll", function() {
            if (this.pageYOffset >= parseInt(scope.offset)) {
                element.addClass(scope.scrollClass);
            } else {
                element.removeClass(scope.scrollClass);
            }
        });
    }
  };
})
Run Code Online (Sandbox Code Playgroud)

所以你可以像这样使用它:

<navbar change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></navbar>
Run Code Online (Sandbox Code Playgroud)

要么

<div change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></div>
Run Code Online (Sandbox Code Playgroud)


Fre*_*tem 16

这是我的解决方案,它不是那么棘手,并且允许您通过简单的ng-class指令将其用于多个标记.像这样你可以为每个案例选择类和scrollPos.

你的App.js:

angular.module('myApp',[])
    .controller('mainCtrl',function($window, $scope){
        $scope.scrollPos = 0;

        $window.onscroll = function(){
            $scope.scrollPos = document.body.scrollTop || document.documentElement.scrollTop || 0;
            $scope.$apply(); //or simply $scope.$digest();
        };
    });
Run Code Online (Sandbox Code Playgroud)

你的index.html:

<html ng-app="myApp">
    <head></head>
    <body>
        <section ng-controller="mainCtrl">
            <p class="red" ng-class="{fix:scrollPos >= 100}">fix me when scroll is equals to 100</p>
            <p class="blue" ng-class="{fix:scrollPos >= 150}">fix me when scroll is equals to 150</p>
        </section>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

这里工作JSFiddle

编辑:

由于$apply()实际上是调用$rootScope.$digest()就可以直接使用$scope.$digest(),而不是$scope.$apply()针对具体情况决定更好的性能.
长话短说:$apply() 将始终有效但强制$digest所有可能导致性能问题的范围.