1 angular.module('uiRouterSample.contacts', [ 2 'ui.router' 3 ]) 4 5 .config( 6 [ '$stateProvider', '$urlRouterProvider', 7 function ($stateProvider, $urlRouterProvider) { 8 $stateProvider 9 ////////////// 10 // Contacts // 11 ////////////// 12 .state('contacts', { 13 14 // With abstract set to true, that means this state can not be explicitly activated. 15 // It can only be implicitly activated by activating one of its children. 16 /** 17 * 18 * 抽象路由模板,該狀態永遠不會被激活 19 * 只會被其子狀態隱式激活 20 * 在本例子中 就是被導航中的ui-sref=contacts.list激活的 21 * */ 22 abstract: true, 23 24 // This abstract state will prepend '/contacts' onto the urls of all its children. 25 /** 26 * 這個抽象狀態會預置/contacts到其全部的子狀態中 27 * 28 * */ 29 url: '/contacts', 30 31 // Example of loading a template from a file. This is also a top level state, 32 // so this template file will be loaded and then inserted into the ui-view 33 // within index.html. 34 templateUrl: 'app/contacts/contacts.html', 35 36 // Use `resolve` to resolve any asynchronous controller dependencies 37 // *before* the controller is instantiated. In this case, since contacts 38 // returns a promise, the controller will wait until contacts.all() is 39 // resolved before instantiation. Non-promise return values are considered 40 // to be resolved immediately. 41 /** 42 * resolve處理異步數據調用,在控制器實例化以前 43 *在這個例子中,contacts返回一個promise,控制器會等到promise處理完以後再進行初始化 44 *non-promise會當即resolve 45 */ 46 resolve: { 47 contacts: ['contacts', 48 function( contacts){ 49 return contacts.all(); 50 }] 51 }, 52 53 // You can pair a controller to your template. There *must* be a template to pair with. 54 /*** 55 * 爲template添加控制器。 56 * 必須與template配對 57 * 58 */ 59 controller: ['$scope', '$state', 'contacts', 'utils', 60 function ( $scope, $state, contacts, utils) { 61 62 // Add a 'contacts' field in this abstract parent's scope, so that all 63 // child state views can access it in their scopes. Please note: scope 64 // inheritance is not due to nesting of states, but rather choosing to 65 // nest the templates of those states. It's normal scope inheritance. 66 $scope.contacts = contacts; 67 68 $scope.goToRandom = function () { 69 var randId = utils.newRandomKey($scope.contacts, "id", $state.params.contactId); 70 71 72 // $state.go() can be used as a high level convenience method 73 // for activating a state programmatically. 74 /** 75 * go()方法是一個高級又便利的方法 76 *用於激活一個動態的狀態 77 */ 78 $state.go('contacts.detail', { contactId: randId }); 79 }; 80 }] 81 }) 82 83 ///////////////////// 84 // Contacts > List // 85 ///////////////////// 86 87 // Using a '.' within a state name declares a child within a parent. 88 // So you have a new state 'list' within the parent 'contacts' state. 89 /** 90 * 在狀態中用一個'.'才分割父狀態和子狀態, 91 * 全部如今建立了一個新的'list'狀態位於父狀態'contacts'中 92 */ 93 .state('contacts.list', { 94 95 // Using an empty url means that this child state will become active 96 // when its parent's url is navigated to. Urls of child states are 97 // automatically appended to the urls of their parent. So this state's 98 // url is '/contacts' (because '/contacts' + ''). 99 /** 100 * 用空的url表示這個子狀態會在其父狀態導航到時被激活 101 * 子狀態會自動添加 102 * 因此這個狀態的url='/contacts'+'' 103 */ 104 url: '', 105 106 // IMPORTANT: Now we have a state that is not a top level state. Its 107 // template will be inserted into the ui-view within this state's 108 // parent's template; so the ui-view within contacts.html. This is the 109 // most important thing to remember about templates. 110 /** 111 * 如今咱們有一個非頂級的狀態 112 *這個模板會出入到其父狀態的ui-view中:也就是contact.html中的ui-view 113 *這是模板中很重要的性質 114 */ 115 templateUrl: 'app/contacts/contacts.list.html' 116 }) 117 118 /////////////////////// 119 // Contacts > Detail // 120 /////////////////////// 121 122 // You can have unlimited children within a state. Here is a second child 123 // state within the 'contacts' parent state. 124 /** 125 * 一個狀態的子狀態是無限的,這是contacts的第二個子狀態 126 */ 127 .state('contacts.detail', { 128 129 // Urls can have parameters. They can be specified like :param or {param}. 130 // If {} is used, then you can also specify a regex pattern that the param 131 // must match. The regex is written after a colon (:). Note: Don't use capture 132 // groups in your regex patterns, because the whole regex is wrapped again 133 // behind the scenes. Our pattern below will only match numbers with a length 134 // between 1 and 4. 135 /** 136 * url上能夠有參數,定義形式:param 或者 {param} 137 * 若是使用{},也能夠定義成一個正則表達式,參數必須匹配正則 138 * 139 */ 140 141 // Since this state is also a child of 'contacts' its url is appended as well. 142 // So its url will end up being '/contacts/{contactId:[0-9]{1,4}}'. When the 143 // url becomes something like '/contacts/42' then this state becomes active 144 // and the $stateParams object becomes { contactId: 42 }. 145 /** 146 * /contacts/42 147 * 這樣的url就能訪問該狀態 148 * 並且$stateParams對象就變成了{contactId:42} 149 * 150 */ 151 url: '/{contactId:[0-9]{1,4}}', 152 153 // If there is more than a single ui-view in the parent template, or you would 154 // like to target a ui-view from even higher up the state tree, you can use the 155 // views object to configure multiple views. Each view can get its own template, 156 // controller, and resolve data. 157 /** 158 * 若是父template不止一個ui-view 159 * 或者想訪問更往上的狀態(—from state tree) 160 * 能夠使用views對象來配置多views,每一個view均可以從他本身的template,controller,resolve data中獲取 161 */ 162 163 // View names can be relative or absolute. Relative view names do not use an '@' 164 // symbol. They always refer to views within this state's parent template. 165 // Absolute view names use a '@' symbol to distinguish the view and the state. 166 // So 'foo@bar' means the ui-view named 'foo' within the 'bar' state's template. 167 /** 168 * view的名字有相對和絕對兩種 169 * 相對的視圖名字不須要用@標誌 170 * 這些view總會在當前狀態的父template中展現 171 * 172 * 絕對名稱的view使用@標誌來區分狀態和視圖view 173 * foo@bar bar狀態的foo view 174 */ 175 views: { 176 177 // So this one is targeting the unnamed view within the parent state's template. 178 /** 179 * ''指向父template中未命名的view 180 */ 181 '': { 182 templateUrl: 'app/contacts/contacts.detail.html', 183 controller: ['$scope', '$stateParams', 'utils', 184 function ( $scope, $stateParams, utils) { 185 $scope.contact = utils.findById($scope.contacts, $stateParams.contactId); 186 }] 187 }, 188 189 // This one is targeting the ui-view="hint" within the unnamed root, aka index.html. 190 // This shows off how you could populate *any* view within *any* ancestor state. 191 /** 192 * ui-view=hint 操做的是root 也就是index.html 193 * 194 */ 195 'hint@': { 196 template: 'This is contacts.detail populating the "hint" ui-view' 197 }, 198 199 // This one is targeting the ui-view="menuTip" within the parent state's template. 200 /** 201 * 這個指向父狀態template中的menuTip 202 */ 203 'menuTip': { 204 // templateProvider is the final method for supplying a template. 205 // There is: template, templateUrl, and templateProvider. 206 /** 207 * templateProvider是提供模板的底層方法 208 * 209 */ 210 templateProvider: ['$stateParams', 211 function ( $stateParams) { 212 // This is just to demonstrate that $stateParams injection works for templateProvider. 213 // $stateParams are the parameters for the new state we're transitioning to, even 214 // though the global '$stateParams' has not been updated yet. 215 /** 216 *這裏僅僅只是展現$stateParams怎麼注入templateProvider的 217 */ 218 return '<hr><small class="muted">Contact ID: ' + $stateParams.contactId + '</small>'; 219 }] 220 } 221 } 222 }) 223 224 ////////////////////////////// 225 // Contacts > Detail > Item // 226 ////////////////////////////// 227 228 .state('contacts.detail.item', { 229 230 // So following what we've learned, this state's full url will end up being 231 // '/contacts/{contactId}/item/:itemId'. We are using both types of parameters 232 // in the same url, but they behave identically. 233 url: '/item/:itemId', 234 views: { 235 236 // This is targeting the unnamed ui-view within the parent state 'contact.detail' 237 // We wouldn't have to do it this way if we didn't also want to set the 'hint' view below. 238 // We could instead just set templateUrl and controller outside of the view obj. 239 '': { 240 templateUrl: 'app/contacts/contacts.detail.item.html', 241 controller: ['$scope', '$stateParams', '$state', 'utils', 242 function ( $scope, $stateParams, $state, utils) { 243 $scope.item = utils.findById($scope.contact.items, $stateParams.itemId); 244 245 $scope.edit = function () { 246 // Here we show off go's ability to navigate to a relative state. Using '^' to go upwards 247 // and '.' to go down, you can navigate to any relative state (ancestor or descendant). 248 // Here we are going down to the child state 'edit' (full name of 'contacts.detail.item.edit') 249 $state.go('.edit', $stateParams); 250 }; 251 }] 252 }, 253 254 // Here we see we are overriding the template that was set by 'contacts.detail' 255 'hint@': { 256 template: ' This is contacts.detail.item overriding the "hint" ui-view' 257 } 258 } 259 }) 260 261 ///////////////////////////////////// 262 // Contacts > Detail > Item > Edit // 263 ///////////////////////////////////// 264 265 // Notice that this state has no 'url'. States do not require a url. You can use them 266 // simply to organize your application into "places" where each "place" can configure 267 // only what it needs. The only way to get to this state is via $state.go (or transitionTo) 268 /** 269 * 當一個狀態並不必定非要有url 能夠經過$scope.go 或者ui-sref 指向 270 */ 271 .state('contacts.detail.item.edit', { 272 views: { 273 274 // This is targeting the unnamed view within the 'contacts.detail' state 275 // essentially swapping out the template that 'contacts.detail.item' had 276 // inserted with this state's template. 277 '@contacts.detail': { 278 templateUrl: 'app/contacts/contacts.detail.item.edit.html', 279 controller: ['$scope', '$stateParams', '$state', 'utils', 280 function ( $scope, $stateParams, $state, utils) { 281 $scope.item = utils.findById($scope.contact.items, $stateParams.itemId); 282 $scope.done = function () { 283 // Go back up. '^' means up one. '^.^' would be up twice, to the grandparent. 284 /** 285 * 退回父狀態 286 * ^.^表示退回兩次 便是grandparent 287 */ 288 $state.go('^', $stateParams); 289 }; 290 }] 291 } 292 } 293 }); 294 } 295 ] 296 );
angular.module('uiRouterSample.contacts', [
'ui.router'
])
.config(
[ '$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$stateProvider
//////////////
// Contacts //
//////////////
.state('contacts', {
// With abstract set to true, that means this state can not be explicitly activated.
// It can only be implicitly activated by activating one of its children.
/**
*
* 抽象路由模板,該狀態永遠不會被激活
* 只會被其子狀態隱式激活
* 在本例子中 就是被導航中的ui-sref=contacts.list激活的
* */
abstract: true,
// This abstract state will prepend '/contacts' onto the urls of all its children.
/**
* 這個抽象狀態會預置/contacts到其全部的子狀態中
*
* */
url: '/contacts',
// Example of loading a template from a file. This is also a top level state,
// so this template file will be loaded and then inserted into the ui-view
// within index.html.
templateUrl: 'app/contacts/contacts.html',
// Use `resolve` to resolve any asynchronous controller dependencies
// *before* the controller is instantiated. In this case, since contacts
// returns a promise, the controller will wait until contacts.all() is
// resolved before instantiation. Non-promise return values are considered
// to be resolved immediately.
/**
* resolve處理異步數據調用,在控制器實例化以前
*在這個例子中,contacts返回一個promise,控制器會等到promise處理完以後再進行初始化
*non-promise會當即resolve
*/
resolve: {
contacts: ['contacts',
function( contacts){
return contacts.all();
}]
},
// You can pair a controller to your template. There *must* be a template to pair with.
/***
* 爲template添加控制器。
* 必須與template配對
*
*/
controller: ['$scope', '$state', 'contacts', 'utils',
function ( $scope, $state, contacts, utils) {
// Add a 'contacts' field in this abstract parent's scope, so that all
// child state views can access it in their scopes. Please note: scope
// inheritance is not due to nesting of states, but rather choosing to
// nest the templates of those states. It's normal scope inheritance.
$scope.contacts = contacts;
$scope.goToRandom = function () {
var randId = utils.newRandomKey($scope.contacts, "id", $state.params.contactId);
// $state.go() can be used as a high level convenience method
// for activating a state programmatically.
/**
* go()方法是一個高級又便利的方法
*用於激活一個動態的狀態
*/
$state.go('contacts.detail', { contactId: randId });
};
}]
})
/////////////////////
// Contacts > List //
/////////////////////
// Using a '.' within a state name declares a child within a parent.
// So you have a new state 'list' within the parent 'contacts' state.
/**
* 在狀態中用一個'.'才分割父狀態和子狀態,
* 全部如今建立了一個新的'list'狀態位於父狀態'contacts'中
*/
.state('contacts.list', {
// Using an empty url means that this child state will become active
// when its parent's url is navigated to. Urls of child states are
// automatically appended to the urls of their parent. So this state's
// url is '/contacts' (because '/contacts' + '').
/**
* 用空的url表示這個子狀態會在其父狀態導航到時被激活
* 子狀態會自動添加
* 因此這個狀態的url='/contacts'+''
*/
url: '',
// IMPORTANT: Now we have a state that is not a top level state. Its
// template will be inserted into the ui-view within this state's
// parent's template; so the ui-view within contacts.html. This is the
// most important thing to remember about templates.
/**
* 如今咱們有一個非頂級的狀態
*這個模板會出入到其父狀態的ui-view中:也就是contact.html中的ui-view
*這是模板中很重要的性質
*/
templateUrl: 'app/contacts/contacts.list.html'
})
///////////////////////
// Contacts > Detail //
///////////////////////
// You can have unlimited children within a state. Here is a second child
// state within the 'contacts' parent state.
/**
* 一個狀態的子狀態是無限的,這是contacts的第二個子狀態
*/
.state('contacts.detail', {
// Urls can have parameters. They can be specified like :param or {param}.
// If {} is used, then you can also specify a regex pattern that the param
// must match. The regex is written after a colon (:). Note: Don't use capture
// groups in your regex patterns, because the whole regex is wrapped again
// behind the scenes. Our pattern below will only match numbers with a length
// between 1 and 4.
/**
* url上能夠有參數,定義形式:param 或者 {param}
* 若是使用{},也能夠定義成一個正則表達式,參數必須匹配正則
*
*/
// Since this state is also a child of 'contacts' its url is appended as well.
// So its url will end up being '/contacts/{contactId:[0-9]{1,4}}'. When the
// url becomes something like '/contacts/42' then this state becomes active
// and the $stateParams object becomes { contactId: 42 }.
/**
* /contacts/42
* 這樣的url就能訪問該狀態
* 並且$stateParams對象就變成了{contactId:42}
*
*/
url: '/{contactId:[0-9]{1,4}}',
// If there is more than a single ui-view in the parent template, or you would
// like to target a ui-view from even higher up the state tree, you can use the
// views object to configure multiple views. Each view can get its own template,
// controller, and resolve data.
/**
* 若是父template不止一個ui-view
* 或者想訪問更往上的狀態(—from state tree)
* 能夠使用views對象來配置多views,每一個view均可以從他本身的template,controller,resolve data中獲取
*/
// View names can be relative or absolute. Relative view names do not use an '@'
// symbol. They always refer to views within this state's parent template.
// Absolute view names use a '@' symbol to distinguish the view and the state.
// So 'foo@bar' means the ui-view named 'foo' within the 'bar' state's template.
/**
* view的名字有相對和絕對兩種
* 相對的視圖名字不須要用@標誌
* 這些view總會在當前狀態的父template中展現
*
* 絕對名稱的view使用@標誌來區分狀態和視圖view
* foo@bar bar狀態的foo view
*/
views: {
// So this one is targeting the unnamed view within the parent state's template.
/**
* ''指向父template中未命名的view
*/
'': {
templateUrl: 'app/contacts/contacts.detail.html',
controller: ['$scope', '$stateParams', 'utils',
function ( $scope, $stateParams, utils) {
$scope.contact = utils.findById($scope.contacts, $stateParams.contactId);
}]
},
// This one is targeting the ui-view="hint" within the unnamed root, aka index.html.
// This shows off how you could populate *any* view within *any* ancestor state.
/**
* ui-view=hint 操做的是root 也就是index.html
*
*/
'hint@': {
template: 'This is contacts.detail populating the "hint" ui-view'
},
// This one is targeting the ui-view="menuTip" within the parent state's template.
/**
* 這個指向父狀態template中的menuTip
*/
'menuTip': {
// templateProvider is the final method for supplying a template.
// There is: template, templateUrl, and templateProvider.
/**
* templateProvider是提供模板的底層方法
*
*/
templateProvider: ['$stateParams',
function ( $stateParams) {
// This is just to demonstrate that $stateParams injection works for templateProvider.
// $stateParams are the parameters for the new state we're transitioning to, even
// though the global '$stateParams' has not been updated yet.
/**
*這裏僅僅只是展現$stateParams怎麼注入templateProvider的
*/
return '<hr><small class="muted">Contact ID: ' + $stateParams.contactId + '</small>';
}]
}
}
})
//////////////////////////////
// Contacts > Detail > Item //
//////////////////////////////
.state('contacts.detail.item', {
// So following what we've learned, this state's full url will end up being
// '/contacts/{contactId}/item/:itemId'. We are using both types of parameters
// in the same url, but they behave identically.
url: '/item/:itemId',
views: {
// This is targeting the unnamed ui-view within the parent state 'contact.detail'
// We wouldn't have to do it this way if we didn't also want to set the 'hint' view below.
// We could instead just set templateUrl and controller outside of the view obj.
'': {
templateUrl: 'app/contacts/contacts.detail.item.html',
controller: ['$scope', '$stateParams', '$state', 'utils',
function ( $scope, $stateParams, $state, utils) {
$scope.item = utils.findById($scope.contact.items, $stateParams.itemId);
$scope.edit = function () {
// Here we show off go's ability to navigate to a relative state. Using '^' to go upwards
// and '.' to go down, you can navigate to any relative state (ancestor or descendant).
// Here we are going down to the child state 'edit' (full name of 'contacts.detail.item.edit')
$state.go('.edit', $stateParams);
};
}]
},
// Here we see we are overriding the template that was set by 'contacts.detail'
'hint@': {
template: ' This is contacts.detail.item overriding the "hint" ui-view'
}
}
})
/////////////////////////////////////
// Contacts > Detail > Item > Edit //
/////////////////////////////////////
// Notice that this state has no 'url'. States do not require a url. You can use them
// simply to organize your application into "places" where each "place" can configure
// only what it needs. The only way to get to this state is via $state.go (or transitionTo)
/**
* 當一個狀態並不必定非要有url 能夠經過$scope.go 或者ui-sref 指向
*/
.state('contacts.detail.item.edit', {
views: {
// This is targeting the unnamed view within the 'contacts.detail' state
// essentially swapping out the template that 'contacts.detail.item' had
// inserted with this state's template.
'@contacts.detail': {
templateUrl: 'app/contacts/contacts.detail.item.edit.html',
controller: ['$scope', '$stateParams', '$state', 'utils',
function ( $scope, $stateParams, $state, utils) {
$scope.item = utils.findById($scope.contact.items, $stateParams.itemId);
$scope.done = function () {
// Go back up. '^' means up one. '^.^' would be up twice, to the grandparent.
/**
* 退回父狀態
* ^.^表示退回兩次 便是grandparent
*/
$state.go('^', $stateParams);
};
}]
}
}
});
}
]
);