当用户将浏览器窗口滚动到某个点以下时,我正在切换#page div的类。
到目前为止我所做的工作很好:
<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.');
}
});
};
});
虽然这不是动态的,但如果我在滚动回调中更改scope.boolChangeClass的值,则ng-class不会更新。
所以我的问题是:当用户滚动到特定点以下时,如何使用AngularJS切换#page类?
答案 0 :(得分:86)
感谢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();
});
};
});
答案 1 :(得分: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);
}
});
}
};
})
所以你可以像这样使用它:
<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>
答案 2 :(得分: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();
};
});
您的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>
编辑:
由于
$apply()
实际上是在调用$rootScope.$digest()
直接使用$scope.$digest()
代替$scope.$apply()
根据具体情况改善表现。
长话短说:$apply()
将始终有效但强制$digest
可能导致所有范围 性能问题。
答案 3 :(得分:2)
也许这有助于:)
控制器
$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 })
}
}
})
答案 4 :(得分:0)
性能怎么样?
scope.applyAsync
减少整体摘要周期数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">
答案 5 :(得分:-4)
他们说,指令不是“在有角度的世界里面”。因此,在更改内容时,您必须使用apply来重新使用