Javascript 使用AngularJS的AngularUI路由器在一个页面上显示多个历史视图
在我的AngularJS应用程序中,我有一个关于页面,其中有几个小节。所有这些子部分都位于同一页面上,并且是同一模板的一部分。但是,我想通过它自己的URL访问每个部分,如果匹配,该URL将向下滚动到正确的部分 我将各州设置为:Javascript 使用AngularJS的AngularUI路由器在一个页面上显示多个历史视图,javascript,angularjs,angular-ui-router,Javascript,Angularjs,Angular Ui Router,在我的AngularJS应用程序中,我有一个关于页面,其中有几个小节。所有这些子部分都位于同一页面上,并且是同一模板的一部分。但是,我想通过它自己的URL访问每个部分,如果匹配,该URL将向下滚动到正确的部分 我将各州设置为: .state('about', { url: "/about", templateUrl: "partials/about.html", }) .state('about.team', { url: "/about/team", templ
.state('about', {
url: "/about",
templateUrl: "partials/about.html",
})
.state('about.team', {
url: "/about/team",
templateUrl: "partials/about.html"
})
.state('about.office', {
url: "/about/office",
templateUrl: "partials/about.html"
})
.state('about.other', {
url: "/about/other",
templateUrl: "partials/about.html"
});
在“关于”页面上,我有一个菜单,如:
<div class="menu">
<a ui-sref-active="selected"
ui-sref="about.team">The Team</a>
<a ui-sref-active="selected"
ui-sref="about.office">The Office</a>
<a ui-sref-active="selected"
ui-sref="about.other">Other</a>
</div>
您可以在此处看到该应用程序:
对于类似()的示例,您可以看到它在页面加载后根据url向下滚动到正确的部分。。。并且不使用散列,而是使用实际的url。我将使用window.scrollTo或jquery scrollTo插件创建一个scrollTo指令
例如:
使用window.scrollTo
Jquery滚动到插件:
在页面加载时,滚动到由hashtag或任何其他url参数定义的视图。例子:
www.sample.com#aboutUs或www.samplecom?view=aboutUs您可以尝试这种方法,创建一个指令,在单击时触发滚动。
您可以将此指令作为属性添加到链接中。其中,sref属性将是目标div的id
app.directive('scrollTo', function() {
return {
link: function(scope, element, attrs) {
element.bind('click', function() {
var divPosition = $(attrs.sRef).offset();
$('html, body').animate({
scrollTop: divPosition.top
}, "slow");
});
}
};
});
在滚动时,我应该:
1. bind to "scroll" events,
2. compare if I reached the position of each headers, using "element.offset().top"
(将此标题设置为指令后。(我应该将标题设置为指令,检查如何从ngtutorial.com/learn/scope生成目录)
加载时(我更喜欢使用hashtags,因为我可以只使用$anchorScroll()或使用.when()),无论如何,加载时更新的示例如下:
1. http://ngtutorial.com/guide.html#/learn-filter.html
2. http://ngtutorial.com/learn/route.html#/_tblcontents_5
如果你不喜欢hashtags,你可以解析location.url()我在自己的应用程序中用来做滚动控制(和滚动间谍的东西),而不是使用locationHash。我自己还没有尝试过这个解决方案,但我想它会起作用
您需要在重要div(滚动到的位置)上声明某种类型的条目id
然后,您可以使用url/about/:locale声明状态“about.stately”(在ui中,路由器stateParams不必是整数)。然后在about.stately的控制器中,您可以执行以下操作(从角度滚动自述文件):
根据控制器中的$stateParams.locale选择要滚动到的元素。请小心等待,直到所有子指令和内容加载完毕-您可能需要$evalAsync才能使其正常工作。但我认为这就是它的要点。这就是我目前尝试的:
// get the current path
var x=$location.path();
// say x='about/team'
//read the last tag and set scrollTo to the top offset of desired div
if(lasttag(x)==team){
scroll to top offset of TEAM div;
}
else if(lasttag(x)==office){
scroll to top offset of OFFICE div;
}
var scrolled = false;
var listenToScroll = false;
$('.subsection').each(function(i) {
var position = $(this).position();
$(this).scrollspy({
min: position.top,
max: position.top + $(this).outerHeight(),
onEnter: function(element, position) {
if(element.id){
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about.'+element.id);
}
} else {
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about');
}
}
}
});
});
$scope.startListenToScroll = function() {
listenToScroll = true;
}
$scope.stopListenToScroll = function(){
listenToScroll = false;
}
$scope.$on('$stateChangeStart', function(){
$scope.stopListenToScroll();
});
$scope.$on('$stateChangeSuccess', function(){
console.log(scrolled);
if( !scrolled ) {
var link = $state.current.name.split('.');
if(link.length>1){
var divPosition = $( '#' + link[1] ).offset();
$('body').stop(true,true).animate({ scrollTop: divPosition.top }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
} else {
$('body').stop(true,true).animate({ scrollTop: 0 }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
}
} else {
$scope.startListenToScroll();
scrolled = false;
}
});
正如你所看到的,我听stateChangeSuccess而不是点击!这样我就可以连接到任何状态更改,不管它们是由链接还是浏览器历史按钮调用的,并根据需要执行滚动
我会在开始更改时立即关闭scrollspy,这样滚动动画就不会调用另一个状态更改(因为您可能会滚动其他部分以创建假历史记录条目)。然后在动画完成后再次打开scrollspy,以便我可以再次侦听滚动事件
stateChangeSuccess在页面加载时触发,因此它可以处理URL的任何粘贴
我有一个名为scrolled
的变量,这样我就可以跟踪状态更改是否是由用户滚动引起的。这是因为我不需要在用户滚动自己时设置scrollTop的动画
想法?您需要做的是在页面顶部创建一个指令,该指令位于ui路由器之外,用于监视状态,然后根据正确的定位点滚动。无需使用TemplateURL,因为您尝试实现的是某种平滑。ui路由器不会对状态设置限制您的状态对象的签名,因此您可以简单地添加属性:
.state('about.office', {
url: "/about/office"
,templateUrl: "partials/about.html"
,scrollToId = "divAboutOffice";
})
然后,控制器可以在注入$state服务时访问此数据
$('html, body').animate({
scrollTop: $($state.current.scrollToId).offset().top
}, "slow");
假设您在HTML中包含了id=“divaboutofice”
(假设我的jQuery引用是正确的;我不使用jQuery,所以我不确定。)
根据您的需要,您可以将该动画()
另外:你不必像我一样使用“id”——如果你真的想按属性搜索元素,你可以利用现有的ui-sref
。在您的示例中,它似乎与$state.current.name
匹配,它不应该依赖于hashtags或查询参数,而是实际的URL,无论我是否使用HTML5模式!您可以在url中将分隔符添加到单独的部分。e、 g.#关于/home
<代码>#关于/office
。然后,您可以将散列
按/
进行拆分,并在有分区时滚动到所需位置。这不是我想做的!它应该是一个URL,而不是依赖于散列/about/your opportunity
是https://devart.withgoogle.com/#/about/your-opportunity
,但格式类似于url的一部分。这是因为他们关闭了HTML5模式。在我的实现中,HTML5模式将被打开,因此不能依赖哈希。@Jashwant你能举例说明你的意思吗?它在HTML5模式下如何工作?谢谢。你能详细说明代码的哪些部分可以做什么吗?(最好将最重要的片段复制到答案中)好的,我已经设法让它滚动,它自然地更新了URL,因为上面有href。但我需要它来处理历史记录和页面加载。那么我该如何调用滚动呢?为此,您可以在AppCtrl中创建一个基本控制器,您可以使用该逻辑函数AppCtrl($state){var divPosition=$('#'+$state.name).offset();$('html,body').animate({scrollTop:divPosition.top},“slow”)}请展示一个示例,然后我可以更新示例应用程序中的代码来测试它。请记住,它需要在页面加载时启动,如果用户使用浏览器的后退和前进按钮。T
.state('about.office', {
url: "/about/office"
,templateUrl: "partials/about.html"
,scrollToId = "divAboutOffice";
})
$('html, body').animate({
scrollTop: $($state.current.scrollToId).offset().top
}, "slow");