State Manager

$stateProvider工作的方式与Angular's v1 router相近,但是他更加注重状态

  • 状态对应于应用程序中某个位置,整体的UI和导航A state corresponds to a "place" in the application in terms of the overall UI and navigation.
  • 状态通过控制器、模板、视图属性描述了UI和他的机制。
  • 状态通常都包含相同的东西,分解出这些共同点主要通过嵌套状态

最简单的例子

最简单的方式可以像这样添加

<!-- 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?

当状态被激活时,他的模板会被自动插入至他父状态的ui-view中。如果这是一个顶级状态,比如上例中contacts没有父状态,他的父模板就为index.html

眼下,'contacts'还不能被激活,让我们看看怎么激活这个状态

激活一个状态

有三种方式激活一个状态:

  1. 调用$state.go()方法Call $state.go(). 高层次的简单的方法. Learn More
  2. 点击ui-sref指示器中的链接 . Learn More
  3. 导航至state关联的url. Learn More.

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.

$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.

$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.
$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:
$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 its 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.
<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 willnot 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'
})

Or use controllerAs syntax if preferred:

$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:

$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.

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.

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.

If any of these dependencies are promises, they will be resolved and converted to a valuebefore the controller is instantiated and the $routeChangeSuccess event is fired.

The resolve property is a map object. The map object contains key/value pairs of:

  • key – {string}: a name of a dependency to be injected into the controller.
  • 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.

$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".
             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 instatiate 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.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.

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

State Change Events

All these events are fired at the $rootScope level.

  • $stateChangeStart - fired when the transition begins.
    $rootScope.$on('$stateChangeStart', 
    function(event, toState, toParams, fromState, fromParams){ ... })
    
    Note: Use event.preventDefault() to prevent the transition from happening.
    $rootScope.$on('$stateChangeStart', 
    function(event, toState, toParams, fromState, fromParams){ 
        event.preventDefault(); 
        // transitionTo() promise will be rejected with 
        // a 'transition prevented' error
    })
    
  • $stateNotFound - v0.3.0 - fired when a requested statecannot 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 specialunfoundState object is passed to the listener handler, you can see its three properties in the example. Useevent.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, seeHow To: Lazy load states
    // somewhere, assume lazy.state has not been defined
    $state.go("lazy.state", {a:1, b:2}, {inherit:false});
    
    // somewhere else
    $scope.$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.
    $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 '$scope' broadcasts the event.

    $scope.$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 loaded,after the DOM is rendered. The '$scope' of the view emits the event.

    $scope.$on('$viewContentLoaded', 
    function(event){ ... });
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值