1、Angular-Ui Router 状态概要

431人阅读 评论(0) 收藏 举报
分类:


状态管理器.

新的状态管理器($stateProvider) 类似于Angular's v1 的路由工作方式, 但更完美.

  • A state corresponds to a "place" in the application in terms of the overall UI and navigation. 
    在整个UI和导航方面,一个状态对应于应用程序中的“位置”。
  • A state (via the controller / template / view properties) describes what the UI looks like and does at that place.
    一个状态(通过controller / template / view属性)描述UI在那个地方是什么样子的。
  • States often have things in common, and the primary way of factoring out these commonalities in this model is via the state hierarchy, i.e. parent/child states aka nested states.
    状态通常有一些共同点,在这个模型中分解这些共性的主要方法是通过状态层次结构,即父/子状态,即嵌套状态。

The simplest form of state
最简单的状态形式

A state in its simplest form can be added like this (typically within module.config):

最简单形式的状态可以像这样添加(一般在module.config中添加):
<!-- 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>'
})

Where does the template get inserted?
模板在哪里插入?

When a state is activated, its templates are automatically inserted into the ui-view of its parent state's template. If it's a top-level state—which 'contacts' is because it has no parent state–then its parent template is index.html.

当一个状态被激活时,它的模板会自动被插入到它的父状态模板的ui视图中。如果是顶级状态,即“联系人”是因为它没有父状态,那么它的父模板是index.html。

Right now, the 'contacts' state won't ever be activated. So let's see how we can activate a state. 
现在,“联系人”状态永远不会被激活。我们来看看如何激活一个状态。

Activating a state
激活状态

There are three main ways to activate a state:
激活一个状态有三种主要方式:

  1. Call $state.go(). High-level convenience method. Learn More 
    调用$state.go()方法,高级的使用方法。详情
  2. Click a link containing the ui-sref directive. Learn More
    单击包含ui-sref指令的标签。详情
  3. Navigate to the url associated with the state. Learn More
    导航到与状态相关联的url。详情.

Templates
模板

There are several methods for configuring a state's template.
有几种配置状态模板的方法。

As seen above, the simplest way to set your template is via the template config property.
如上面所示,设置模板的最简单方法是通过(template属性)配置。

$stateProvider.state('contacts', {
  template: '<h1>My Contacts</h1>'
})

Instead of writing the template inline you can load a partial. (This is probably how you'll set templates most of the time.)
您可以通过URL加载一个模板,而不是内联地编写模板。(这是推荐的做法。)

$stateProvider.state('contacts', {
  templateUrl: 'contacts.html'
})

templateUrl can also be a function that returns a url. It takes one preset parameter, stateParams, which is not injected.
templateUrl也可以是返回url的回调函数。它需要一个预设的$stateParams参数,而不是注入的参数。

$stateProvider.state('contacts', {
  templateUrl: function ($stateParams){
    return '/partials/contacts.' + $stateParams.filterBy + '.html';
  }
})

Or you can use a template provider function which can be injected, has access to locals, and must return template HTML, like this:
或者您可以使用一个模板提供者函数,它可以使用注入,可以访问本地数据,但必须返回模板HTML,如下:

$stateProvider.state('contacts', {
  templateProvider: function ($timeout, $stateParams) {
    return $timeout(function () {
      return '<h1>' + $stateParams.contactId + '</h1>'
    }, 100);
  }
})

If you'd like your <ui-view> to have some default content before it's populated by a state activation, you can do that as well. The contents will be replaced as soon as a state is activated and populates the ui-view with a template.
如果您希望在它被一个状态激活之前有一些默认的内容,那么您也可以这样做。当一个状态被激活并使用一个模板填充ui-view时,内容将被替换。

<body>
    <ui-view>
        <i>Some content will load here!</i>
    </ui-view>
</body>

Controllers
控制器

You can assign a controller to your template. Warning: The controller will not be instantiated if template is not defined.
您可以将控制器分配给您的模板。警告:如果模板没有定义,控制器将不会被实例化。

You set your controller like this:
您可以像这样设置您的控制器:

$stateProvider.state('contacts', {
  template: '<h1>{{title}}</h1>',
  controller: function($scope){
    $scope.title = 'My Contacts';
  }
})

Or if you already have a controller defined on the module, like this:
或者您已经像这样定义了一个控制器

$stateProvider.state('contacts', {
  template: ...,
  controller: 'ContactsCtrl'
})

Alternatively using the "controller as" syntax the above becomes:
或者使用“controllerAs”语法,以上就变成了:

$stateProvider.state('contacts', {
  template: '<h1>{{contact.title}}</h1>',
  controller: function(){
    this.title = 'My Contacts';
  },
  controllerAs: 'contact'
})

$stateProvider.state('contacts', {
  template: ...,
  controller: 'ContactsCtrl as contact'
})

Or for more advanced needs you can use the controllerProvider to dynamically return a controller function or string for you:
或者,对于更高级的需求,您可以使用controllerProvider来动态地返回控制器函数或字符串:

$stateProvider.state('contacts', {
  template: ...,
  controllerProvider: function($stateParams) {
      var ctrlName = $stateParams.type + "Controller";
      return ctrlName;
  }
})

Controllers can use the $scope.$on() method to listen for events fired by state transitions.
控制器可以使用$scope.$on()方法侦听状态转换所触发的事件。

Controllers are instantiated on an as-needed basis, when their corresponding scopes are created, i.e. when the user manually navigates to a state via a URL, $stateProvider will load the correct template into the view, then bind the controller to the template's scope.
控制器在需要的基础上实例化,当它们对应的作用域被创建时,即当用户通过URL手动导航到状态时,$stateProvider将把正确的模板加载到视图中,然后将控制器绑定到模板的作用域。

Resolve
延迟加载

You can use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.
您可以使用Resolve给您的状态控制器提供自定义的内容或数据。Resolve是一个可选的依赖关系映射,它可被注入到控制器中。

If any of these dependencies are promises, they will be resolved and converted to a value beforethe controller is instantiated and the $stateChangeSuccess event is fired.
这些依赖项在控制器实例化之前,它们将被解析并转换为一个值,并触发$statechangesucess事件。

The resolve property is a map object. The map object contains key/value pairs of:
Resolve属性是一个map对象。map对象包含键/值对:

  • key – {string}: a name of a dependency to be injected into the controller.
    key – {string}:要注入到控制器中的依赖项的名称。
  • factory - {string|function}:
    • If string, then it is an alias for a service.
      如果是字符串,则它是服务的名称。
    • Otherwise if function, then it is injected and the return value is treated as the dependency. If the result is a promise, it is resolved before the controller is instantiated and its value is injected into the controller.
      否则,如果是一个函数,那么它是一个依赖注入,返回值则是依赖注入项。如果结果是一个协议,那么在控制器实例化之前,它就会被解析,并且它的值被注入到控制器中。

Examples:
示例

Each of the objects in resolve below must be resolved (via deferred.resolve() if they are a promise) before the controller is instantiated. Notice how each resolve object is injected as a parameter into the controller.
下面解析的每个对象会在控制器实例化之前解析完毕(via deferred.resolve() if they are a promise)。注意,如何将每个解析对象作为参数注入到控制器。

$stateProvider.state('myState', {
      resolve:{

         // Example using function with simple return value.
         // Since it's not a promise, it resolves immediately.
         simpleObj:  function(){
            return {value: 'simple!'};
         },

         // Example using function with returned promise.
         // This is the typical use case of resolve.
         // You need to inject any services that you are
         // using, e.g. $http in this example
         promiseObj:  function($http){
            // $http returns a promise for the url data
            return $http({method: 'GET', url: '/someUrl'});
         },

         // Another promise example. If you need to do some 
         // processing of the result, use .then, and your 
         // promise is chained in for free. This is another
         // typical use case of resolve.
         promiseObj2:  function($http){
            return $http({method: 'GET', url: '/someUrl'})
               .then (function (data) {
                   return doSomeStuffFirst(data);
               });
         },        

         // Example using a service by name as string.
         // This would look for a 'translations' service
         // within the module and return it.
         // Note: The service could return a promise and
         // it would work just like the example above
         translations: "translations",

         // Example showing injection of service into
         // resolve function. Service then returns a
         // promise. Tip: Inject $stateParams to get
         // access to url parameters.
         translations2: function(translations, $stateParams){
             // Assume that getLang is a service method
             // that uses $http to fetch some translations.
             // Also assume our url was "/:lang/home".
             return translations.getLang($stateParams.lang);
         },

         // Example showing returning of custom made promise
         greeting: function($q, $timeout){
             var deferred = $q.defer();
             $timeout(function() {
                 deferred.resolve('Hello!');
             }, 1000);
             return deferred.promise;
         }
      },

      // The controller waits for every one of the above items to be
      // completely resolved before instantiation. For example, the
      // controller will not instantiate until promiseObj's promise has 
      // been resolved. Then those objects are injected into the controller
      // and available for use.  
      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;
      }
   })

Learn more about how resolved dependencies are inherited down to child states.
了解更多关于如何将依赖关系继承到子状态的问题。

Attach Custom Data to State Objects
向状态对象附加自定义数据

You can attach custom data to the state object (we recommend using a data property to avoid conflicts).
您可以将自定义数据附加到状态对象(我们建议使用数据属性来避免冲突)。

// Example shows an object-based state and a string-based state
var contacts = { 
    name: 'contacts',
    templateUrl: 'contacts.html',
    data: {
        customData1: 5,
        customData2: "blue"
    }  
}
$stateProvider
  .state(contacts)
  .state('contacts.list', {
    templateUrl: 'contacts.list.html',
    data: {
        customData1: 44,
        customData2: "red"
    } 
  })

With the above example states you could access the data like this:
在上面的示例中,您可以这样访问数据:

function Ctrl($state){
    console.log($state.current.data.customData1) // outputs 5;
    console.log($state.current.data.customData2) // outputs "blue";
}

Learn more about how custom data properties are inherited down to child states.
了解更多关于自定义数据属性是如何继承到子状态的。

onEnter and onExit callbacks

There are also optional 'onEnter' and 'onExit' callbacks that get called when a state becomes active and inactive respectively. The callbacks also have access to all the resolved dependencies.
还有可选的“onEnter”和“onExit”回调函数,当一个状态变为活动状态和不活动状态时就会被调用。回调也可以访问所有已解析的依赖项。

$stateProvider.state("contacts", {
  template: '<h1>{{title}}</h1>',
  resolve: { 
     title: function () { 
       return 'My Contacts' 
     } 
  },
  controller: function($scope, title){
    $scope.title = title;
  },
  onEnter: function(title){
    if(title){ ... do something ... }
  },
  onExit: function(title){
    if(title){ ... do something ... }
  }
})

State Change Events
状态变化事件

NOTE: State change events are deprecated, DISABLED and replaced by Transition Hooks as of version 1.0 (details
注意:状态更改事件已被弃用,禁用并替换为版本1.0(详细信息))

All these events are fired at the $rootScope level.
所有这些事件都在$rootScope级别上被触发。

  • $stateChangeStart - fired when the transition begins.在转换开始时触发。
$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams, options){ ... })

Note: Use event.preventDefault() to prevent the transition from happening.
注意:使用event.preventDefault()来防止转换的发生。

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams, options){ 
    event.preventDefault(); 
    // transitionTo() promise will be rejected with 
    // a 'transition prevented' error
})
  • $stateNotFound - v0.3.0 - fired when a requested state cannot be found using the provided state name during transition. The event is broadcast allowing any handlers a single chance to deal with the error (usually by lazy-loading the unfound state). A special unfoundState object is passed to the listener handler, you can see its three properties in the example. Use event.preventDefault() to abort the transition (transitionTo() promise will be rejected with a 'transition aborted' error). For a more in-depth example on lazy loading states, see How To: Lazy load states
// somewhere, assume lazy.state has not been defined
$state.go("lazy.state", {a:1, b:2}, {inherit:false});

// somewhere else
$rootScope.$on('$stateNotFound', 
function(event, unfoundState, fromState, fromParams){ 
    console.log(unfoundState.to); // "lazy.state"
    console.log(unfoundState.toParams); // {a:1, b:2}
    console.log(unfoundState.options); // {inherit:false} + default options
})
  • $stateChangeSuccess - fired once the state transition is complete.状态转换完成后触发。
$rootScope.$on('$stateChangeSuccess', 
function(event, toState, toParams, fromState, fromParams){ ... })
  • $stateChangeError - fired when an error occurs during transition. It's important to note that if you have any errors in your resolve functions (javascript errors, non-existent services, etc) they will not throw traditionally. You must listen for this $stateChangeError event to catch ALL errors. Use event.preventDefault() to prevent the $UrlRouter from reverting the URL to the previous valid location (in case of a URL navigation).
    在转换过程中发生错误时触发。需要注意的是,如果在解析函数中有任何错误(javascript错误、不存在的服务等等),它们就不会按传统方式抛出。您必须侦听此$stateChangeError事件以捕获所有错误。使用event.preventDefault()防止$url路由器将URL恢复到以前的有效位置(以URL导航为例)。
$rootScope.$on('$stateChangeError', 
function(event, toState, toParams, fromState, fromParams, error){ ... })

View Load Events
视图加载事件

  • $viewContentLoading - fired once the view begins loading, before the DOM is rendered. The '$rootScope' broadcasts the event.一旦视图开始加载,在DOM被呈现之前就被触发。“$rootScope”广播这个事件。
$rootScope.$on('$viewContentLoading', 
function(event, viewConfig){ 
    // Access to all the view config properties.
    // and one special property 'targetView'
    // viewConfig.targetView 
});
  • $viewContentLoaded - fired once the view is loadedafter the DOM is rendered. The '$scope' of the view emits the event.在DOM被渲染之后,就会触发视图。视图的“$scope”会发出事件。
$scope.$on('$viewContentLoaded', 
function(event){ ... });
探讨请加微信:


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:294789次
    • 积分:2993
    • 等级:
    • 排名:第12162名
    • 原创:85篇
    • 转载:10篇
    • 译文:5篇
    • 评论:154条
    最新评论