绑定类切换到窗口滚动事件
当用户在某个点以下滚动浏览器窗口时,我正在切换#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.'); } }); }; });
(当他们滚动他们的窗口下面的标题,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.'); } }); }; });
虽然这不是dynamic的,但如果我在滚动callback中更改scope.boolChangeClass的值,那么ng-class不会更新。
所以我的问题是:当用户滚动到某个点以下时,最好是使用AngularJS切换#page的类。
感谢Flek在他的评论中回答我的问题:
<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(); }); }; });
为什么你们都build议重型作业? 我不明白为什么这不是一个“angular度”的解决scheme:
.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); } }); } }; })
所以你可以像这样使用它:
<navbar change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></navbar>
要么
<div change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></div>
这是我的解决scheme,这不是那么棘手,并允许您通过一个简单的ng-class指令来使用它的几个标记。 像这样你可以select类和每个案例的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(); }; });
您的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>
在这里工作JSFiddle
编辑:
因为
$apply()
实际上是调用$rootScope.$digest()
你可以直接使用$scope.$digest()
而不是$scope.$apply()
来取得更好的性能。
长话短说:$apply()
将始终工作,但强制所有范围的$digest
可能会导致性能问题。
也许这可以帮助:)
调节器
$scope.scrollevent = function($e){ // Your code }
HTML
<div scroll scroll-event="scrollevent">//scrollable content</div>
要么
<body scroll scroll-event="scrollevent">//scrollable content</body>
指示
.directive("scroll", function ($window) { return { scope: { scrollEvent: '&' }, link : function(scope, element, attrs) { $("#"+attrs.id).scroll(function($e) { scope.scrollEvent != null ? scope.scrollEvent()($e) : null }) } } })
性能呢?
- 始终消除事件以减less计算
- 使用
scope.applyAsync
来减less整个摘要循环次数
function debounce(func, wait) { var timeout; return function () { var context = this, args = arguments; var later = function () { timeout = null; func.apply(context, args); }; if (!timeout) func.apply(context, args); clearTimeout(timeout); timeout = setTimeout(later, wait); }; } angular.module('app.layout') .directive('classScroll', function ($window) { return { restrict: 'A', link: function (scope, element) { function toggle() { angular.element(element) .toggleClass('class-scroll--scrolled', window.pageYOffset > 0); scope.$applyAsync(); } angular.element($window) .on('scroll', debounce(toggle, 50)); toggle(); } }; });
3.如果你不需要触发观察者/摘要,那么使用compile
.directive('classScroll', function ($window, utils) { return { restrict: 'A', compile: function (element, attributes) { function toggle() { angular.element(element) .toggleClass(attributes.classScroll, window.pageYOffset > 0); } angular.element($window) .on('scroll', utils.debounce(toggle, 50)); toggle(); } }; });
你可以像<header class-scroll="header--scrolled">
一样使用它
指令并不像他们所说的那样是“在有棱的世界里面”。 所以当你改变东西的时候你必须使用apply来重新使用它