标签:
$stateProvider 和angular的router功能相似,但它只关心状态(state)的变化
一个最简单的state形式如下所示:
<!-- in index.html --> <body ng-controller="MainCtrl"> <section ui-view></section> </body>
// in app-states.js (or whatever you want to name it) $stateProvider.state(‘contacts‘, { template: ‘<h1>My Contacts</h1>‘ })
如果state 被激活了,该 state 的template 就会被自动地插入到它的parent template的 ui-view 中。如果该state处于top-level(即没有父级的state).则它的parent template 就是 index.html
有三种激活state的方式
$state.go(to, [, toParams], [, options])
$state.go() 提供一个转换到 new state 的方便快捷的方式,它会在内部调用 $state.transitionTo 方法,并且自动设置options 参数为
{ location: true, inherit: true, relative: $state.$current, notify: true }
to
$state.go()可以传入一个state name 或者 一个相对路径作为第一个参数, 如果一个路径以 ^ 或者 . 开头,则改路径是相对的,否则是绝对的。
几个例子:
$state.go(‘contact.detail‘)
会转换到 ‘contact.detail‘ state$state.go(‘^‘)
转换到 parent state.$state.go(‘^.sibling‘)
转换到 sibling state.$state.go(‘.child.grandchild‘)
转换到 grandchild state.toParams
toParams 以一个对象直接量的形式填充到 $stateParams
如果参数为指定将会从当前已经定义的参数中继承, sibilings state 可以共享继承自parent state的参数,child state 可以继承当前state的参数
options
各种配置参数
2. 点击包含ui-sref指令的链接
用法:
ui-sref=‘stateName‘ --- 转换到一个state,无附加参数
ui-sref=‘stateName({param: value, param: value})‘; --- 转换到一个state,并且传递参数
resolve属性是一个可选的对象,应当被作为依赖注入到controller中,当 $stateChangeSuccess 事件触发时,resolve会在controller实例化之前被解析。
resolve是一对键值对,其中
$stateProvider.state(‘myState‘, { resolve:{ // 直接返回一个值,由于不是promise,会被立即解析 simpleObj: function(){ return {value: ‘simple!‘}; }, // 返回要给promise // 这是一种典型的用法 // 你需要在function中注入你用到的所有服务,比如这里的 $http服务 promiseObj: function($http){ // $http returns a promise for the url data return $http({method: ‘GET‘, url: ‘/someUrl‘}); }, // 另外一种常见用法,如果你需要对返回值进行操作,可以使用链式的 .then() 方法 promiseObj2: function($http){ return $http({method: ‘GET‘, url: ‘/someUrl‘}) .then (function (data) { return doSomeStuffFirst(data); }); }, // 直接使用已经定义的service的名称, // 这里会在当前的module中寻找名为 translations 的service,并将其返回 // 注意: 这里的service也可以返回一个promise,然后像上面那样操作 translations: "translations", // 直接将 service 注入到 resolve 函数的例子 // service 返回一个promise // 小建议: 注入 $stateParams 来访问 url 参数 translations2: function(translations, $stateParams){ // 我们假定 getLang 是一个service 的方法,使用$http服务从url为 "/:lang/home" 来获取数据 return translations.getLang($stateParams.lang); }, // 返回自定义promise的例子 greeting: function($q, $timeout){ var deferred = $q.defer(); $timeout(function() { deferred.resolve(‘Hello!‘); }, 1000); return deferred.promise; } }, // controller 会等上面所有的item完全解析之后才进行实例化。 // 在下面的例子中,所有的promise对象在controller实例化之前都已经全部初始化并且注入到controller中等待被使用 controller: function($scope, simpleObj, promiseObj, promiseObj2, translations, translations2, greeting){ $scope.simple = simpleObj.value; // You can be sure that promiseObj is ready to use! $scope.items = promiseObj.data.items; $scope.items = promiseObj2.items; $scope.title = translations.getLang("english").title; $scope.title = translations2.title; $scope.greeting = greeting; } })
几种嵌套state的方法
1. 使用 . 号,例如 .state(‘ contacts.list ‘, {})
2. 使用 ui-router.stateHelper 从一个state树创建state
3. 使用 parent 属性和string类型的 parent state. 例如, parent: ‘contacts‘
4. 使用 parent 属性和object类型的 parent state. 例如, parent: contacts (这里 contacts 是一个stateObject)
abstract states 的 child state 会继承它的url prefix。除此之外没有其他的继承
child state 会从它的祖先state(s)继承 resolved dependencies, 并且可以覆盖他们。你可以在 child states 的 resolve function 中注入 resolved dependencies。
直接看例子吧,翻译成中文说不明白
$stateProvider.state(‘parent‘, { resolve:{ resA: function(){ return {‘value‘: ‘A‘}; } }, controller: function($scope, resA){ $scope.resA = resA.value; } }) .state(‘parent.child‘, { resolve:{ // 这里的 resA 继承自parent state, 可以将其注入到 resolve function,和 controller 中 resB: function(resA){ return {‘value‘: resA.value + ‘B‘}; } }, controller: function($scope, resA, resB){ $scope.resA2 = resA.value; $scope.resB = resB.value; }
注意:resolve 的key必须被注入到 child states 中,如果你想在 children state 实例化之前解析 promise 的话
抽象state 可以拥有child state,但是不能使其自身得到激活. 一个抽象state就是不能被转换到的状态,当它的任何一个后代state被激活时它会被隐式的激活。
你可能会用到抽象state的一些场景
1,在所有 child state的url之前插入一个url prefix
2,通过它自身的 ui-view(s) 插入一个 template,用来装载 child states
3,提供 resolved dependencies 给 child states 使用
4,提供 自定义data给child states 或者 事件监听器使用
5,执行 onEnter 或 onExit 函数
记住:抽象state 仍然需要它自己的 template 来装载它的孩子们。所以,如果你正在使用抽象state做上面的事情,你需要额外的设置 template: ‘<ui-view/>‘;
抽象state使用示例:
为后代插入url prefix 的例子
$stateProvider .state(‘contacts‘, { abstract: true, url: ‘/contacts‘, // Note: abstract still needs a ui-view for its children to populate. // You can simply add it inline here. template: ‘<ui-view/>‘ }) .state(‘contacts.list‘, { // url will become ‘/contacts/list‘ url: ‘/list‘ //...more }) .state(‘contacts.detail‘, { // url will become ‘/contacts/detail‘ url: ‘/detail‘, //...more })
插入template 来装载后代的例子
$stateProvider .state(‘contacts‘, { abstract: true, templateUrl: ‘contacts.html‘ }) .state(‘contacts.list‘, { // contacts.list.html的html片段会被插入到 contacts.html中 templateUrl: ‘contacts.list.html‘ }) .state(‘contacts.detail‘, { // 同样contacts.detail.html的html片段也会被插入到 contacts.html中 templateUrl: ‘contacts.detail.html‘ })
<!-- contacts.html --> <h1>Contacts Page</h1> <div ui-view></div>
综合应用
$stateProvider
.state(‘contacts‘, {
abstract: true,
url: ‘/contacts‘,
templateUrl: ‘contacts.html‘,
controller: function($scope){
$scope.contacts = [{ id:0, name: "Alice" }, { id:1, name: "Bob" }];
}
})
.state(‘contacts.list‘, {
url: ‘/list‘,
templateUrl: ‘contacts.list.html‘
})
.state(‘contacts.detail‘, {
url: ‘/:id‘, // url 会变为 ‘/contacts/:id‘
templateUrl: ‘contacts.detail.html‘,
// 继承了contacts state 的$scope
controller: function($scope, $stateParams){
$scope.person = $scope.contacts[$stateParams.id];
}
})
<!-- contacts.html --> <h1>Contacts Page</h1> <div ui-view></div>
<!-- contacts.list.html --> <ul> <li ng-repeat="person in contacts"> <a ng-href="#/contacts/{{person.id}}">{{person.name}}</a> </li> </ul>
<!-- contacts.detail.html --> <h2>{{ person.name }}</h2>
当你需要设置多个views时,要用到state的views属性,states是要给对象
views 会覆盖 state 的template 属性
当你设置了 views 对象时,state 的 templateUrl, template, templateProvider属性会被忽略,在这种情况下,你需要一个parent view 来安置这些 views, 你可以定义一个包含一个template的抽象state,一个在该抽象state template 内部的child state来容纳这个 views 对象。
views 对象中的key 名应该与 ui-view中的名称匹配
<!-- index.html --> <body> <div ui-view="filters"></div> <div ui-view="tabledata"></div> <div ui-view="graph"></div> </body>
$stateProvider .state(‘report‘, { views: { ‘filters‘: { ... templates and/or controllers ... }, ‘tabledata‘: {}, ‘graph‘: {}, } })
每个在views中的view可以单独设置它自己的template,controller和resolve
$stateProvider .state(‘report‘,{ views: { ‘filters‘: { templateUrl: ‘report-filters.html‘, controller: function($scope){ ... controller stuff just for filters view ... } }, ‘tabledata‘: { templateUrl: ‘report-table.html‘, controller: function($scope){ ... controller stuff just for tabledata view ... } }, ‘graph‘: { templateUrl: ‘report-graph.html‘, controller: function($scope){ ... controller stuff just for graph view ... } } } })
view names 相对vs绝对
每个view会遵从 viewname@statename 的机制在后台分配一个绝对名称,这里 viewname 是写在view 指令中那个,statename 是 view指令所在的 那个state 的绝对名称。
你可以根绝绝对命名语法写自己的view names
上面要给例子可以用绝对命名改写成以下形式:
.state(‘report‘,{ views: { ‘filters@‘: { }, ‘tabledata@‘: { }, ‘graph@‘: { } } })
这里 view names 全部采用绝对命名, 分别指向位于未命名state的 template 中的三个 views ( "filters" , "tabledata", "graph").由于root state未命名,所以这里@后面什么也没有。未命名的 template 就是 index.html
绝对命名法可以让我们做很多强大的view 定位,看栗子
<!-- index.html (root unnamed template) --> <body ng-app> <div ui-view></div> <!-- contacts.html plugs in here --> <div ui-view="status"></div> </body> <!-- contacts.html --> <h1>My Contacts</h1> <div ui-view></div> <div ui-view="detail"></div> <!-- contacts.detail.html --> <h1>Contacts Details</h1> <div ui-view="info"></div>
$stateProvider .state(‘contacts‘, { // 这个template会被插入到为命名的ui-view中,因为他是top level 的 //state,它的父级state 的template就是index.html templateUrl: ‘contacts.html‘ }) .state(‘contacts.detail‘, { views: { //////////////////////////////////// // Relative Targeting // // Targets parent state ui-view‘s // //////////////////////////////////// // 相对地命中父级state-contacts中的 detail view // <div ui-view=‘detail‘/> within contacts.html "detail" : { }, // 相对地命中父级state-contacts中的未命名view // <div ui-view/> within contacts.html "" : { }, /////////////////////////////////////////////////////// // 绝对 Targeting using ‘@‘ // //命中当前state或者其祖先state的任何view // /////////////////////////////////////////////////////// //绝对命中当前state, ‘contacts.detail‘. // <div ui-view=‘info‘/> within contacts.detail.html "info@contacts.detail" : { } // 绝对命中 ‘contacts‘ state 中的detail view // <div ui-view=‘detail‘/> within contacts.html "detail@contacts" : { } // 绝对命中父级state-- ‘contacts‘ 中的未命名view. // <div ui-view/> within contacts.html "@contacts" : { } //绝对命中未命名根state中的status view. // <div ui-view=‘status‘/> within index.html "status@" : { } // 绝对命中未命名根state中的未命名view // <div ui-view/> within index.html "@" : { } });
搞得很烦,到此为止!!
标签:
原文地址:http://www.cnblogs.com/walle2/p/4960733.html