"之前。但我似乎遇到了一个竞赛条件,即在 quickNav 编译之前,滚动条就已经启动了(滚动条上有一个 ng-hide
,不确定是否是这个原因造成的,但它是在 DOM 中)。
如果我在控制台中运行该代码块,滚动就会按预期运行。
我想把它移到控制器中会更有效,或者更有可能移到指令中。但我的运气并不好。**怎样才能让这段代码在 AngularJS 中运行?
下面是一个简单的指令,点击后将滚动到一个元素:
myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm) {
$elm.on('click', function() {
$("body").animate({scrollTop: $elm.offset().top}, "slow");
});
}
}
});
演示:http://plnkr.co/edit/yz1EHB8ad3C59N6PzdCD?p=preview
有关创建指令的帮助,请查看 http://egghead.io 上的视频,从 #10 "第一个指令"开始。
编辑:若要滚动到由 href 指定的特定元素,只需选中 attrs.href
。
myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm, attrs) {
var idToScroll = attrs.href;
$elm.on('click', function() {
var $target;
if (idToScroll) {
$target = $(idToScroll);
} else {
$target = $elm;
}
$("body").animate({scrollTop: $target.offset().top}, "slow");
});
}
}
});
然后就可以这样使用了:<div scroll-on-click></div>
滚动到点击的元素。 或者 <a scroll-on-click href="#element-id"></div>
滚动到具有 id 的元素。
如果您想使用,这是一个更好的指令:
您可以滚动到页面中的任何元素:
.directive('scrollToItem', function() {
return {
restrict: 'A',
scope: {
scrollTo: "@"
},
link: function(scope, $elm,attr) {
$elm.on('click', function() {
$('html,body').animate({scrollTop: $(scope.scrollTo).offset().top }, "slow");
});
}
}})
用法(例如,点击 div 'back-to-top'将滚动到 id scroll-top):
<a id="top-scroll" name="top"></a>
<div class="back-to-top" scroll-to-item scroll-to="#top-scroll">
由于使用了 html、body 元素,chrome、firefox、safari 和 IE 也支持该功能。
感谢 Andy 提供的示例,这对我很有帮助。由于我正在开发单页滚动,并且不希望 Angular 在使用 hashbang URL 时刷新,因此我最终采用了略有不同的策略。我还希望保留浏览器的后退/前进操作。
我没有使用指令和哈希值,而是在 $location.search 上使用了 $scope.$watch,并从那里获取目标。这样就有了一个简洁的锚标签
a ng-href="#/?scroll=myElement">My element<a ng-href="#/?scroll=myElement">My element</a>
我在 app.js 中将监视代码链入 my module 声明,如下所示:
.run(function($location, $rootScope) {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0;
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
})
上述代码需要注意的是,如果直接从不同的路径访问 URL,DOM 可能无法及时加载,无法满足 jQuery'$target.offset() 的调用。解决方法是将这段代码嵌套在 $viewContentLoaded 监视器中。最终代码如下
.run(function($location, $rootScope) {
$rootScope.$on('$viewContentLoaded', function() {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
var scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
});
})
已在 Chrome 浏览器和 FF 浏览器上测试