我在我的应用程序中使用了出色的 ui-router
模块.作为其中的一部分,我使用命名视图来管理应用程序中的动态子导航".
考虑以下几点:
$urlRouterProvider.otherwise('/person/list');$stateProvider.state('人', {网址:'/人',摘要:真实,}).state('person.list', {网址:'/列表',意见:{主要的@": {模板网址:person.list.html",控制器:'PersonListController'}}}).state('person.details', {网址:'/{id}',意见:{'主要的@': {templateUrl: "person.details.html",控制器:'PersonController'},'导航@':{templateUrl: "person.nav.html",控制器:'PersonNavController'}}});
当用户首次访问该应用时,他们会看到一个人员列表.当他们点击一个人时,他们会被带到详细信息页面.很基本的东西.如果有帮助,这里是标记...
<aside ui-view="nav"></aside><div ui-view="main"></div></div>
但是,PersonNavController
调用 REST 服务来获取人员列表,因此在查看人员时,用户可以导航同级元素.使用上述方法会导致模板和控制器重新渲染,从而在每次点击后导致延迟,尽管内容从未改变.
有没有办法让 'nav@'
视图保持加载状态,并且只刷新 'main@'
视图?
我在这种情况下使用 ui-router
的方式是:将视图移到最小公分母上时间>.
换句话说:如果 ui-view="nav"
在所有细节之间共享并且对所有细节都相同(因为它应该只加载一次) - 它应该是 list
状态的一部分 (detail
状态的父级)
父状态定义会这样调整:
.state('person.list', {网址:'/列表',意见:{主要的@": {模板网址:person.list.html",控制器:'PersonListController'}//这里我们针对 person.list.html//及其 ui-view="nav"'nav@person.list': {templateUrl: "person.nav.html",控制器:'PersonNavController'}}
那么诀窍在哪里?在角度 ui-router
的力量下.我们可以,在每个状态定义期间,以当前视图为目标.现在,nav
视图是 list
状态定义的一部分 - 即它不会在细节切换期间重新加载(另请检查 这里了解更多说明)
我们只需要使用定义的命名约定,请参阅:
查看名称 - 相对名称与绝对名称上述文档中引用的几行:
浏览量:{/////////////////////////////////相对定位////目标父状态 ui-view 的///////////////////////////////////在此状态的父状态联系人"中相对定位详细信息"视图.//<div ui-view='detail'/>在contacts.html中细节" : { },//相对定位在此状态的父状态联系人"中的未命名视图.//<div ui-view/>在contacts.html中":{},////////////////////////////////////////////////使用 '@' 的绝对定位////以该状态内的任何视图或祖先为目标//////////////////////////////////////////////////绝对针对此状态下的 'info' 视图,'contacts.detail'.//<div ui-view='信息'/>在contacts.detail.html中info@contacts.detail":{}//绝对针对处于联系人"状态的详细信息"视图.//<div ui-view='detail'/>在contacts.html中详细信息@联系人":{ }
I'm using the excellent ui-router
module in my application. As part of this, I'm using named views to manage the 'dynamic sub-navigation' I have in the app.
Consider the following:
$urlRouterProvider.otherwise('/person/list');
$stateProvider
.state('person', {
url: '/person',
abstract: true,
})
.state('person.list', {
url: '/list',
views: {
"main@": {
templateUrl: "person.list.html",
controller: 'PersonListController'
}
}
})
.state('person.details', {
url: '/{id}',
views: {
'main@': {
templateUrl: "person.details.html",
controller: 'PersonController'
},
'nav@': {
templateUrl: "person.nav.html",
controller: 'PersonNavController'
}
}
});
When users first visit the app, they are presented with a list of people. When they click on a person, they are taken to the details page. Pretty basic stuff. Here's the markup if it helps...
<div>
<aside ui-view="nav"></aside>
<div ui-view="main"></div>
</div>
However, the PersonNavController
calls a REST service to get a list of people, so when viewing a person, the user is able to navigate sibling elements. Using the method above causes the template and controller to re-render, thus causing a delay after every click, despite the content never changing.
Is there a way to keep the 'nav@'
view loaded, and only refresh the 'main@'
view?
The way I am using ui-router
in this scenarios is: move the views to the least common denominator.
Other words: In case that ui-view="nav"
is shared among all the details and is the same for all of them (because it should be loaded only once) - it should be part of the list
state (parent of the detail
state)
the parent state defintion would be adjusted like this:
.state('person.list', {
url: '/list',
views: {
"main@": {
templateUrl: "person.list.html",
controller: 'PersonListController'
}
// here we target the person.list.html
// and its ui-view="nav"
'nav@person.list': {
templateUrl: "person.nav.html",
controller: 'PersonNavController'
}
}
So where is the trick? In the power of the angular ui-router
. We can, during each state defintion, target the current view. Now, the nav
view is part of the list
state definition - i.e. it will not be reloaded during the detail switching (also check here for more explanation)
We just have to use the defined naming conventions, see:
View Names - Relative vs. Absolute NamesFew cited lines from the mentioned documentation:
views: {
////////////////////////////////////
// Relative Targeting //
// Targets parent state ui-view's //
////////////////////////////////////
// Relatively targets the 'detail' view in this state's parent state, 'contacts'.
// <div ui-view='detail'/> within contacts.html
"detail" : { },
// Relatively targets the unnamed view in this state's parent state, 'contacts'.
// <div ui-view/> within contacts.html
"" : { },
///////////////////////////////////////////////////////
// Absolute Targeting using '@' //
// Targets any view within this state or an ancestor //
///////////////////////////////////////////////////////
// Absolutely targets the 'info' view in this state, 'contacts.detail'.
// <div ui-view='info'/> within contacts.detail.html
"info@contacts.detail" : { }
// Absolutely targets the 'detail' view in the 'contacts' state.
// <div ui-view='detail'/> within contacts.html
"detail@contacts" : { }