发表于: 2017-04-15 21:30:20

1 1128


如何使用ui-router?

路由(route),几乎所有的MVC(VM)框架都应该具有的特性,因为它是前端构建单页面应用(SPA)必不可少的组成部分。

对于angular而言,自然也有内置的路由模块-ngRoute。但由于功能的局限性,往往不能满足开发需求。于是,AngularUI团队基于ngRoute开发了第三方模块-UI-Router。ngRoute在多视图和嵌套视图上较弱,ui-router弥补了这些缺点。

2.知识剖析

UI-Router注入与配置

和ngRoute一样,UI-Router首先需要作为依赖注入应用

angular.module("myApp", ["ui.router"]).config(function($stateProvider){

        $stateProvider.state(stateName, stateConfig);

                })



html标签中设置视图插入位置: 如

<div ui-view=""></div>


UI-router基本参数

$stateProvider:配置应用状态

用法:$stateProvider.state(stateName,

                stateConfig)

stateConfig:对象,该路由的具体配置项,url:默认相对路径(以^开头的是绝对路径)

views:每个子视图可以包含自己的模板、控制器和预载入数据。设置多视图。如果在单个状态不需要此属性。

template:

                HTML字符串或者返回HTML字符串的函数(一般用templateUrl)<br>templateUrl: HTML模板的路径或者返回HTML模板路径的函数<br>controller、controllerProvider:指定任何已经被注册的控制器或者一个作为控制器的函数<br>resolve:预载入列依赖或数据,注入到控制器中。<br>onEnter,

                onExit:路由进入OR退出时执行的函数

1.view:当一个页面需要嵌入多个视图时,可以配置参数,这里介绍相对路径的配置,绝对路径用@的形式,可查看官方文档


  <div ui-view="filters"></div>

  <div ui-view="tabledata"></div>

  <div ui-view="graph"></div>


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

      }

    }

})


 resolve:向该路由控制器注入依赖或数据,格式{string|function}

resolve: {promiseObj:  function($http){

            return $http({method: 'GET', url: '/someUrl'})

               .then (function (data) {

                   return doSomeStuffFirst(data);

               });

         }},   

//在controller中注入promiseObj获取值

 controller: function($scope,promiseObj){

          $scope.items = promiseObj.data.items;


data:注入自定义数据。


3.常见问题

1、路由间参数如何传递?

2、嵌套路由父子关系如何定义?


4.解决方案

1、路由间参数如何传递?

一、通过url传递:url中传递参数也有好几种形式,如(ui-sref="a({}),$state.go('a',({}))")

url:"/contacts/:contactId" //url中传入参数为 /contacts/42

url: "/contacts/{contactId}"

//若为查询参数

url: "/contacts?myParam" //将匹配url的“/ contacts?myParam = value”

url: "/contacts?myParam1&myParam2" //will match to url of "/contacts?myParam1=value1&myParam2=wowcool"


二、通过params属性设置

 .state('contacts', {

                        url: "/contacts",

                        params: {

                            param1: null

                        },

                        templateUrl: 'contacts.html'

                    })

<a ui-sref="contacts({param1: value1})">View Contacts</a> or $state.go('contacts', {param1: value1})。


2、嵌套路由父子关系如何定义?

$stateProvider

                    .state('contacts.list', {});//点标记法(推荐)

                $stateProvider //parent属性

                    .state({

                        name: 'list',       // 状态名也可以直接在配置里指定

                        parent: 'contacts'  // 父路由的状态名

                    });

5.编码实战

6.扩展思考

UI-router工作原理?

路由对于前端MVC(VM)而言,就是将hash值(#xxx)与一系列的路由规则进行查找匹配,匹配出一个符合条件的规则,然后根据这个规则,进行数据的获取,以及页面的渲染。

大致过程

1.创建路由规则。

.state('home', {

        url: '/abc',

        template: 'hello world'

    });


首先,$urlRouterProvider创建并存储一个state对象,里面包含着该路由规则的所有配置信息。然后,调用$urlRouterProvider.when(...)方法,进行路由的注册(之前是路由的创建)。

2.路由查找匹配

(1)angular 在刚开始的$digest时,$rootScope会触发$locationChangeSuccess事件(angular在每次浏览器hash change的时候也会触发$locationChangeSuccess事件)(2)ui.router

监听了$locationChangeSuccess事件,于是开始通过遍历一系列rules,进行路由查找匹配

(3)当匹配到路由后,就通过$state.transitionTo(state,...),跳转激活对应的state

(4)最后,完成数据请求和模板的渲染


当我们访问http://xxxx#/abc的时候,这个路由规则被匹配到,对应的模板会被填到某个div[ui-view]中。


一般路由要对rules进行遍历,但ui-router进行了优化:

ui.router在创建路由时,会实例化一个对应的state对象,并存储起来(states集合里面),每一个state对象都有一个state.name进行唯一标识(如:'home')

 当通过ui-sref(会调用$state.go())指令或直接通过$state.go()跳转时,ui-sref="home"指令会给对应的dom添加click事件,然后根据state.name,直接跳转到对应的state,跳转到对应的state之后,ui.router会改变hash,所以触发’$locationChangeSuccess'事件,然后执行回调,在回调中通过一个判断代码规避循环rules。

 所以尽量避免直接使用href="#/xxx"来改变hash,然后跳转到对应state。这么做将进行rules遍历,浪费性能。

7.参考文献

参考一:<a href="http://www.cnblogs.com/01-02/p/6071392.html" target="_blank">angular中的路由</a>

参考二:<a href="https://github.com/angular-ui/ui-router/wiki/Quick-Reference#stateprovider-1"

                      target="_blank">uiroueter官方文档</a></p>

参考三:<a href="https://www.oschina.net/translate/angularjs-ui-router-nested-routes" target="_blank">AngularJS

                ui-router (嵌套路由)</a>


8.更多讨论

uiRouter中还要很多对应事件,了解之后在项目中很有帮助

state事件

$rootScope.$on('$stateChangeStart', function(event,toState, toParams, fromState, fromParams){ ... })

               

$rootScope.$on('$stateNotFound', function(event, unfoundState, fromState, fromParams){ ... })

                

$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ ..  })


$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams,error){ ... })


 view事件:View被加载但是DOM树构建之前时:

$scope.$on('$viewContentLoading', function(event, viewConfig){ ... });

               View被加载而且DOM树构建完成时:$scope.$on('$viewContentLoaded', function(event){ ... });



返回列表 返回列表
评论

    分享到