发表于: 2017-02-17 23:36:23

1 1325


今天完成的事情:

进真实项目资格评审;

分享做复盘项目前台时的一些经验和遇到的问题;

了解学渣乐园需求;

小课堂分享:ui-router的使用


1.背景介绍

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

对于angular而言,自然也有内置的路由模块-ngRoute。但由于功能的局限性,往往不能满足开发需求。于是,AngularUI团队基于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)
templateUrl: HTML模板的路径或者返回HTML模板路径的函数
controller、controllerProvider:指定任何已经被注册的控制器或者一个作为控制器的函数
resolve:预载入列依赖或数据,注入到控制器中。
onEnter, onExit:路由进入OR退出时执行的函数

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

                html
                

$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:注入自定义数据

ronEnter 和 onExit 回调函数,在进入该路由和离开该路由时触发

//这个做登陆验证也不错,进入需要登陆的模块时,检测登陆状态,未登陆就跳转,做一些弹窗也可以 

$stateProvider.state(

     "contacts", {  

          template: '{{title}',  

           resolve: { title: 'My Contacts' },  

          controller: function($scope, title){    

                    $scope.title = title;  },  

onEnter: function(title){    if(title){ ... do something ... }  },  

onExit: function(title){    if(title){ ... do something ... }  } })',  

resolve: 

          { title: 'My Contacts' },  

controller: function($scope, title){    

                $scope.title = title;  },  

onEnter: function(title){    if(title){ ... do something ... }  },  

onExit: function(title){    if(title){ ... do something ... }  } })                

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" //url: "/contacts?myParam1=value1&myParam2=wowcool"

二、通过params属性设置

.state('contacts', {

        url: "/contacts",

        params: {

            param1: null

        },

        templateUrl: 'contacts.html'

    })

uisref or $state.go('contacts', {param1: value1})                

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

$stateProvider

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

 $stateProvider //parent属性

    .state({

        name: 'list',

       // 状态名也可以直接在配置里指定

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

    });                

5.编码实战

.state('field.moduleDetail', {

                    url: '/moduleEdit?id',

                    templateUrl: 'Pages/moduleEdit.html', 

                    controller: 'moduleEditController',

                    controllerAs: 'vm',

                })

 ui-sref="field.moduleDetail({id:item.id})" 

//url 中http://admin.luoboduo.com/#/panel/moduleEdit?id=1                                 .state('field.companyList', { //url:http://admin.luoboduo.com/#/panel/professionMsg (field URL为panel)

                url: '/companyMsg',

                templateUrl: 'Pages/companyMsg.html',

                controller: 'CompanyListController',

                controllerAs: 'vm'            })                


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遍历,浪费性能


明天计划的事情:

开始写学渣乐园前端方案,调研可用插件


遇到的问题:。。。

收获:

如上


返回列表 返回列表
评论

    分享到