AngularJS中ui-router全攻略

来源:互联网 发布:淘宝分享有赏红包在哪 编辑:程序博客网 时间:2024/06/05 17:48

From:http://www.cnblogs.com/darrenji/p/5167999.html


首先是angular-ui-router的基本用法。

■ 如何引用依赖angular-ui-router

 

angular.module('app',["ui.router"])    .config(function($stateProvider){        $stateProvider.state(stateName, stateCofig);    })

 

■ $stateProvider.state(stateName, stateConfig)

stateName是string类型
stateConfig是object类型

//statConfig可以为空对象
$stateProvider.state("home",{});

//state可以有子父级
$stateProvider.state("home",{});
$stateProvider.state("home.child",{})

//state可以是链式的
$stateProvider.state("home",{}).state("about",{}).state("photos",{});

stateConfig包含的字段:template, templateUrl, templateProvider, controller, controllerProvider, resolve, url, params, views, abstract, onEnter, onExit, reloadOnSearch, data

■ $urlRouteProvider

$urlRouteProvider.when(whenPath, toPath)
$urlRouterProvider.otherwise(path)
$urlRouteProvider.rule(handler)

■ $state.go

$state.go(to, [,toParams],[,options])
形参to是string类型,必须,使用"^"或"."表示相对路径;
形参toParams可空,类型是对象;
形参options可空,类型是对象,字段包括:location为bool类型默认true,inherit为bool类型默认true, relative为对象默认$state.$current,notify为bool类型默认为true, reload为bool类型默认为false

$state.go('photos.detail')
$state.go('^')到上一级,比如从photo.detail到photo
$state.go('^.list')到相邻state,比如从photo.detail到photo.list
$state.go('^.detail.comment')到孙子级state,比如从photo.detail到photo.detial.comment

■ ui-sref

ui-sref='stateName'
ui-sref='stateName({param:value, param:value})'

■ ui-view

==没有名称的ui-view

 

<div ui-view></div>$stateProvider.state("home",{    template: "<h1>hi</h1>"})

 

或者这样配置:

 

复制代码
$stateProvider.state("home"{    views: {        "": {            template: "<h1>hi</h1>"        }    }})
复制代码

 

==有名称的ui-view

 

复制代码
<div ui-view="main"></div>$stateProvider.state("home",{    views: {        "main" : {            template: "<h1>hi</h1>"        }    }})
复制代码

 

==多个ui-view

 

复制代码
<div ui-view></div><div ui-view="data"></div>$stateProvider.state("home",{    views: {        "":{template: "<h1>hi</h1>"},        "data": {template: "<div>data</div>"}    }})
复制代码

 


■ 项目文件结构

node_modules/
partials/
.....about.html
.....home.html
.....photos.html
app.js
index.html

■ 创建state和view

app.js

复制代码
var photoGallery = angular.module('photoGallery',["ui.router"]);photoGallery.config(function($stateProvider, $urlRouterProvider){    $urlRouterProvider.otherwise('/home');    $stateProvider        .state('home',{            url: '/home',            templateUrl: 'partials/home.html'        })        .state('photos',{            url: '/photos',            templateUrl: 'partials/photos.html'        })        .state('about',{            url: '/about',            templateUrl: 'partials/about.html'        })})
复制代码

 

index.html

复制代码
<!DOCTYPE html><html lang="en" ng-app="photoGallery"><head>  <meta charset="UTF-8">  <title></title>  <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css"/></head><body>  <h1>Welcome</h1>  <div ui-view></div><script src="node_modules/jquery/dist/jquery.js"></script><script src="node_modules/angular/angular.js"></script><script src="node_modules/angular-ui-router/release/angular-ui-router.js"></script><script src="node_modules/angular-animate/angular-animate.js"></script><script src="node_modules/bootstrap/dist/js/bootstrap.js"></script><script src="node_modules/angular-bootstrap/ui-bootstrap-tpls.js"></script><script src="app.js"></script></body></html>
复制代码

 

■ state之间的跳转

 

index.html

复制代码
<nav class="navbar navbar-inverse"><div class="container-fluid">  <div class="navbar-header">    <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">      <span class="icon-bar"></span>      <span class="icon-bar"></span>      <span class="icon-bar"></span>    </button>    <a ui-sref="home" class="navbar-brand">Home</a>  </div>  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">    <ul class="nav navbar-nav">      <li>        <a ui-sref="photos">Photos</a>      </li>      <li>        <a ui-sref="about">About</a>      </li>    </ul>  </div></div></nav><div ui-view></div>
复制代码

 

以上通过ui-sref属性完成state之间的跳转。

■ 多个view以及state嵌套

有时候,一个页面上可能有多个ui-view,比如:

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

假设,以上页面属于一个名称为parent的state中。

我们知道在ui-router中,一个state大致是这样设置的:

.state('content.photos',{    url: 'photos',    views:{        "body@content":{templateUrl: 'partials/photos.html'}    }})

 

所有state下views下的所有键值对(类似 "body@content":{templateUrl: 'partials/photos.html'})都被放到一个键值集合中。而ui-view的工作原理就是根据自己的属性值,到这个键值集合中去找匹配的键,找到就把对应的页面显示出来。


点击header对应的页面链接,可能会跳转到另外的子页面出现在<div ui-view="body"></div>这个位置。这时候页面出现了子父关系,而每个页面都属于某个state,这样state间就出现了子父关系。这些跳转的子页面,在路由设置中,可能被称为parent.son1, parent.son2...这就是state的嵌套。

在现有的文件结构上增加content.html, header.html,文件结构变为:


node_modules/
partials/
.....about.html
.....home.html
.....photos.html
.....content.html
.....header.html
app.js
index.html

content.html 包含了多各ui-view, 一个ui-view和页头相关,保持不变;令一个ui-view和会根据页头上的点击呈现不同的内容


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


header.html 把原先indext.html中nav部分放到这里来

复制代码
<nav class="navbar navbar-inverse">  <div class="container-fluid">    <div class="navbar-header">      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">        <span class="icon-bar"></span>        <span class="icon-bar"></span>        <span class="icon-bar"></span>      </button>      <a ui-sref="content.home" class="navbar-brand">Home</a>    </div>    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">      <ul class="nav navbar-nav">        <li>          <a ui-sref="content.photos">Photos</a>        </li>        <li>          <a ui-sref="content.about">About</a>        </li>      </ul>    </div>  </div></nav>
复制代码

 

index.html 这时变成了这样

<div ui-view></div>

app.js 路由现在这样设置

 

复制代码
var photoGallery = angular.module('photoGallery',["ui.router"]);photoGallery.config(function($stateProvider, $urlRouterProvider){    $urlRouterProvider.otherwise('home');    $stateProvider        .state('content',{            url: '/',            views:{                "":{templateUrl: 'partials/content.html'},                "header@content":{templateUrl: 'partials/header.html'},            }        })        .state('content.home',{            url: 'home',            views:{                "body@content":{templateUrl: 'partials/home.html'}            }        })        .state('content.photos',{            url: 'photos',            views:{                "body@content":{templateUrl: 'partials/photos.html'}            }        })        .state('content.about',{            url:'about',            views:{                "body@content":{templateUrl: 'partials/about.html'}            }        })})
复制代码

 

这时候,页面是这样呈现出来的:

→ 来到home这个路由

 

.state('content.home',{    url: 'home',    views:{        "body@content":{templateUrl: 'partials/home.html'}    }})

 

以上,告诉我们partials/home.html将会被加载到与"body@content"匹配的ui-view中。暂时对应的ui-view还没有出现,于是等待。

→ 路由看到index.html上的<div ui-view></div>

 

复制代码
.state('content',{    url: '/',    views:{        "":{templateUrl: 'partials/content.html'},        "header@content":{templateUrl: 'partials/header.html'},    }})
复制代码

 

于是,就找到了content这个state下views下的 "":{templateUrl: 'partials/content.html'}这个键值对,把partials/content.html显示出来。

→ 分别加载partials/content.html页面上的各个部分

看到<div ui-view="header"></div>,就加载如下:

"header@content":{templateUrl: 'partials/header.html'},


看到<div ui-view="body"></div>,先加载 "body@content":{templateUrl: 'partials/home.html'}


→ 点击header上的链接

点击<a ui-sref="content.photos">Photos</a>,来到:

.state('content.photos',{    url: 'photos',    views:{        "body@content":{templateUrl: 'partials/photos.html'}    }})

 

把partials/photos.html显示到<div ui-view="body"></div>中去。


点击<div ui-view="body"></div>,来到:

.state('content.about',{    url:'about',    views:{        "body@content":{templateUrl: 'partials/about.html'}    }})

 

把partials/about.html显示到<div ui-view="body"></div>中去。


■ state多级嵌套

以上,在路由设置中,state名称有content, content.photos有了这样的一层嵌套。接下来,要实现state的多级嵌套。

在photos.html页面准备加载一个子页面,叫做photos-list.html;
与photo-list.html页面相邻的还有一个页面,叫做photo-detail.html;
在photo-detail.html页面上加载一个子页面,叫做photos-detail-comment.html;

这样,页面有了嵌套关系,state也相应的会有嵌套关系。

现在,文件结构变成:

node_modules/
partials/
.....about.html
.....home.html
.....photos.html
.....content.html
.....header.html
.....photos-list.html
.....photo-detail.html
.....photos-detail-comment.html
app.js
index.html

photos.html 加一个容纳子页面的ui-view

photos
<div ui-view></div>

如何到达这个子页面呢?修改header中的相关部分如下:

 

复制代码
<nav class="navbar navbar-inverse">  <div class="container-fluid">    <div class="navbar-header">      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">        <span class="icon-bar"></span>        <span class="icon-bar"></span>        <span class="icon-bar"></span>      </button>      <a ui-sref="content.home" class="navbar-brand">Home</a>    </div>    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">      <ul class="nav navbar-nav">        <li>          <a ui-sref="content.photos.list">Photos</a>        </li>        <li>          <a ui-sref="content.about">About</a>        </li>      </ul>    </div>  </div>
复制代码

 

以上,通过<a ui-sref="content.photos.list">Photos</a>来到photos.html的子页面photos-list.html.

photos-list.html 通过2种途径到相邻页photo-detail.html

<h1>photos-list</h1><ul>  <li><a ui-sref="^.detail">我通过相对路径到相邻的state</a></li>  <li><a ui-sref="content.photos.detail">我通过绝对路径到相邻的state</a></li></ul>

 

photo-detail.html 又提供了来到其子页面photos-detail-comment.html的ui-view

<h1>photo-details</h1><a class="btn btn-default" ui-sref=".comment">通过相对路径去子state</a><div ui-view></div>

 

photos-detail-comment.html 则很简单:
<h1>photos-detail-comment</h1>

app.js state多级嵌套的设置为

复制代码
var photoGallery = angular.module('photoGallery',["ui.router"]);photoGallery.config(function($stateProvider, $urlRouterProvider){    $urlRouterProvider.otherwise('home');    $stateProvider        .state('content',{            url: '/',            views:{                "":{templateUrl: 'partials/content.html'},                "header@content":{templateUrl: 'partials/header.html'},            }        })        .state('content.home',{            url: 'home',            views:{                "body@content":{templateUrl: 'partials/home.html'}            }        })        .state('content.photos',{            url: 'photos',            views:{                "body@content":{templateUrl: 'partials/photos.html'}            }        })        .state('content.photos.list',{            url: '/list',            templateUrl: 'partials/photos-list.html'        })        .state('content.photos.detail',{            url: '/detail',            templateUrl: 'partials/photos-detail.html'        })        .state('content.photos.detail.comment',{            url: '/comment',            templateUrl: 'partials/photos-detail-comment.html'        })        .state('content.about',{            url:'about',            views:{                "body@content":{templateUrl: 'partials/about.html'}            }        })})
复制代码

 

■ 抽象state

如果一个state,没有通过链接找到它,那就可以把这个state设置为abstract:true,我们把以上的content和content.photos这2个state设置为抽象。

 

复制代码
.state('content',{    url: '/',    abstract: true,    views:{        "":{templateUrl: 'partials/content.html'},        "header@content":{templateUrl: 'partials/header.html'},    }})....state('content.photos',{    url: 'photos',    abstract: true,    views:{        "body@content":{templateUrl: 'partials/photos.html'}    }})
复制代码

 

那么,当一个state设置为抽象,如果通过ui-sref或路由导航到该state会出现什么结果呢?

--会导航到默认路由上

$urlRouterProvider.otherwise('home');

 

.state('content.home',{    url: 'home',    views:{        "body@content":{templateUrl: 'partials/home.html'}    }})

 

最终把partials/home.html显示出来。

 

■ 使用控制器

在实际项目中,数据大多从controller中来。

首先在路由中设置state所用到的控制器以及控制器别名。

 

复制代码
var photoGallery = angular.module('photoGallery',["ui.router"]);photoGallery.config(function($stateProvider, $urlRouterProvider){    $urlRouterProvider.otherwise('home');    $stateProvider        .state('content',{            url: '/',            abstract: true,            views:{                "":{templateUrl: 'partials/content.html'},                "header@content":{templateUrl: 'partials/header.html'},            }        })        .state('content.home',{            url: 'home',            views:{                "body@content":{                    templateUrl: 'partials/home.html',                    controller: 'HomeController',                    controllerAs: 'ctrHome'                }            }        })        .state('content.photos',{            url: 'photos',            abstract: true,            views:{                "body@content":{                    templateUrl: 'partials/photos.html',                    controller: 'PhotoController',                    controllerAs: 'ctrPhoto'                }            }        })        .state('content.photos.list',{            url: '/list',            templateUrl: 'partials/photos-list.html',            controller: "PhotoListController",            controllerAs: 'ctrPhotoList'        })        .state('content.photos.detail',{            url: '/detail',            templateUrl: 'partials/photos-detail.html',            controller: 'PhotoDetailController',            controllerAs: 'ctrPhotoDetail'        })        .state('content.photos.detail.comment',{            url: '/comment',            templateUrl: 'partials/photos-detail-comment.html'        })        .state('content.about',{            url:'about',            views:{                "body@content":{templateUrl: 'partials/about.html'}            }        })})
复制代码

 

添加controller.js,该文件用来定义所用到的controller.现在的文件结构为:


asserts/
.....css/
.....images/
..........image1.jpg
..........image2.jpg
..........image3.jpg
..........image4.jpg
node_modules/
partials/
.....about.html
.....home.html
.....photos.html
.....content.html
.....header.html
.....photos-list.html
.....photo-detail.html
.....photos-detail-comment.html
app.js
index.html

controllers.js

复制代码
photoGallery.controller('HomeController',['$scope', '$state', function($scope, $state){    this.message = 'Welcome to the Photo Gallery';}]);//别名:ctrPhotophotoGallery.controller('PhotoController',['$scope','$state', function($scope, $state){    this.photos = [        { id: 0, title: 'Photo 1', description: 'description for photo 1', imageName: 'image1.jpg', comments:[            {name: 'user1', comment: 'Nice'},            { name:'User2', comment:'Very good'}        ]},        { id: 1, title: 'Photo 2', description: 'description for photo 2', imageName: 'image2.jpg', comments:[            { name: 'user2', comment: 'Nice'},            { name:'User1', comment:'Very good'}        ]},        { id: 2, title: 'Photo 3', description: 'description for photo 3', imageName: 'image3.jpg', comments:[            {name: 'user1', comment: 'Nice'}        ]},        { id: 3, title: 'Photo 4', description: 'description for photo 4', imageName: 'image4.jpg', comments:[            {name: 'user1', comment: 'Nice'},            { name:'User2', comment:'Very good'},            { name:'User3', comment:'So so'}        ]}    ];    //给子state下controller中的photos赋值    this.pullData = function(){        $scope.$$childTail.ctrPhotoList.photos = this.photos;    }}]);//别名:ctrPhotoListphotoGallery.controller('PhotoListController',['$scope','$state', function($scope, $state){    this.reading = false;    this.photos = new Array();    this.init = function(){        this.reading = true;        setTimeout(function(){            $scope.$apply(function(){                $scope.ctrPhotoList.getData();            });        }, 1500);    }    this.getData = function(){        //调用父state中controller中的方法        $scope.$parent.ctrPhoto.pullData();        /*this.photos = $scope.$parent.ctrPhoto.photos;*/        this.reading = false;    }}]);//别名:ctrPhotoDetailphotoGallery.controller('PhotoDetailController',['$scope', '$state', function($scope,$state){}]);
复制代码

 

以上,通过$scope.$$childTail.ctrPhotoList在父state中的controller中拿到子state中的controller;通过$scope.$parent.ctrPhoto在子state中的controller中拿到父state中的controller。

 

photos-list.html

复制代码
<h1>photos-list</h1><div ng-init="ctrPhotoList.init()">  <div style="margin:auto; width: 40px;" ng-if="ctrPhotoList.reading">    <i class="fa fa-spinner fa-5x fa-pulse"></i>  </div>  <div class="well well-sm" ng-repeat="photo in ctrPhotoList.photos">    <div class="media">      <div class="media-left" style="width:15%;">        <a ui-sref="content.photos.detail">          <img class="img-responsive img-rounded" src="../asserts/images/{{photo.imageName}}" alt="">        </a>      </div>      <div class="media-body">        <h4 class="media-heading">{{photo.title}}</h4>        {{photo.description}}      </div>    </div>  </div></div>
复制代码

 


■ state间如何传路由参数

在content.photos.detail这个state设置接收一个路由参数。

 

复制代码
.state('content.photos.detail',{    url: '/detail/:id',    templateUrl: 'partials/photos-detail.html',    controller: 'PhotoDetailController',    controllerAs: 'ctrPhotoDetail'})
复制代码

 

photos-list.html 送出一个路由参数

复制代码
<h1>photos-list</h1><div ng-init="ctrPhotoList.init()">  <div style="margin:auto; width: 40px;" ng-if="ctrPhotoList.reading">    <i class="fa fa-spinner fa-5x fa-pulse"></i>  </div>  <div class="well well-sm" ng-repeat="photo in ctrPhotoList.photos">    <div class="media">      <div class="media-left" style="width:15%;">        <a ui-sref="content.photos.detail({id:photo.id})">          <img class="img-responsive img-rounded" src="../asserts/images/{{photo.imageName}}" alt="">        </a>      </div>      <div class="media-body">        <h4 class="media-heading">{{photo.title}}</h4>        {{photo.description}}      </div>    </div>  </div></div>
复制代码

以上,通过<a ui-sref="content.photos.detail({id:photo.id})">把路由参数送出。



controller.js PhotoDetailController控制器通过$stateParams获取路由参数

复制代码
...//别名:ctrPhotoDetailphotosGallery.controller('PhotoDetailController', ['$scope', '$state', '$stateParams',    function($scope, $state, $stateParams){        var id = null;        this.photo = null;        this.init = function(){            id = parseInt($stateParams.id);            this.photo = $scope.ctrPhoto.photos[id];        }    }]);
复制代码

 

photos-detail.html 从以上的PhotoDetailController中获取数据。

复制代码
<h1>photo-details</h1><a class="btn btn-default" ui-sref=".comment">通过相对路径去子state</a><a ui-sref="content.photos.list" style="margin-left: 15px;">  <i class="fa fa-arrow-circle-left fa-2x"></i></a><div ng-init="ctrPhotoDetail.init()">  <img class="img-responsive img-rounded" ng-src="../assets/images/{{ctrPhotoDetail.photo.imageName}}"       style="margin:auto; width: 60%;">  <div class="well well-sm" style="margin:auto; width: 60%; margin-top: 15px;">    <h4>{{ctrPhotoDetail.photo.title}}</h4>    <p>{{ctrPhotoDetail.photo.description}}</p>  </div>  <div style="margin:auto; width: 80%; margin-bottom: 15px;">    <button style="margin-top: 10px; width:100%;"            class="btn btn-default" ui-sref=".comment">Comments</button>  </div></div><div ui-view></div>
复制代码

 

■ state间如何传字符串参数

在路由中这样设置:

 

复制代码
.state('content.photos.detail.comment',{    url:'/comment?skip&limit',    templateUrl: 'partials/photos-detail-comment.html',    controller: 'PhotoCommentController',    controllerAs: 'ctrPhotoComment'})
复制代码

 

controllers.js 中修改如下

复制代码
photoGallery.controller('HomeController',['$scope', '$state', function($scope, $state){    this.message = 'Welcome to the Photo Gallery';}]);//别名:ctrPhotophotoGallery.controller('PhotoController',['$scope','$state', function($scope, $state){    this.photos = [        { id: 0, title: 'Photo 1', description: 'description for photo 1', imageName: 'image1.JPG', comments:[            { name:'User1', comment: 'Nice', imageName: 'man.png'},            { name:'User2', comment:'Very good', imageName: 'man.png'},            { name:'User3', comment:'Nice', imageName: 'woman.png'},            { name:'User4', comment:'Very good', imageName: 'woman.png'},            { name:'User5', comment:'Very good', imageName: 'man.png'},            { name:'User6', comment:'Nice', imageName: 'woman.png'},            { name:'User7', comment:'So so', imageName: 'man.png'}        ]},        { id: 1, title: 'Photo 2', description: 'description for photo 2', imageName: 'image2.JPG', comments:[            { name:'User1', comment: 'Nice', imageName: 'man.png'},            { name:'User2', comment:'Very good', imageName: 'man.png'},            { name:'User3', comment:'Nice', imageName: 'woman.png'},            { name:'User4', comment:'Very good', imageName: 'woman.png'}        ]},        { id: 2, title: 'Photo 3', description: 'description for photo 3', imageName: 'image3.JPG', comments:[            { name:'User1', comment: 'Nice', imageName: 'man.png'},            { name:'User2', comment:'Very good', imageName: 'man.png'},            { name:'User3', comment:'Nice', imageName: 'woman.png'},            { name:'User4', comment:'Very good', imageName: 'woman.png'},            { name:'User5', comment:'Very good', imageName: 'man.png'},            { name:'User6', comment:'Nice', imageName: 'woman.png'},            { name:'User7', comment:'So so', imageName: 'man.png'}        ]},        { id: 3, title: 'Photo 4', description: 'description for photo 4', imageName: 'image4.JPG', comments:[            { name:'User6', comment:'Nice', imageName: 'woman.png'},            { name:'User7', comment:'So so', imageName: 'man.png'}        ]}    ];    //给子state下controller中的photos赋值    this.pullData = function(){        $scope.$$childTail.ctrPhotoList.photos = this.photos;    }}]);//别名:ctrPhotoListphotoGallery.controller('PhotoListController',['$scope','$state', function($scope, $state){    this.reading = false;    this.photos = new Array();    this.init = function(){        this.reading = true;        setTimeout(function(){            $scope.$apply(function(){                $scope.ctrPhotoList.getData();            });        }, 1500);    }    this.getData = function(){        //调用父state中controller中的方法        $scope.$parent.ctrPhoto.pullData();        /*this.photos = $scope.$parent.ctrPhoto.photos;*/        this.reading = false;    }}]);//别名:ctrPhotoDetailphotoGallery.controller('PhotoDetailController', ['$scope', '$state', '$stateParams',    function($scope, $state, $stateParams){        var id = null;        this.photo = null;        this.init = function(){            id = parseInt($stateParams.id);            this.photo = $scope.ctrPhoto.photos[id];        }    }]);photoGallery.controller('PhotoCommentController', ['$scope', '$state', '$stateParams',    function($scope, $state, $stateParams){        var id, skip, limit = null;        this.comments = new Array();        this.init = function(){            id = parseInt($stateParams.id);            var photo = $scope.ctrPhoto.photos[id];            if($stateParams.skip){                skip = parseInt($stateParams.skip);            }else{                skip = 0;            }            if($stateParams.limit){                limit = parseInt($stateParams.limit);            }else{                limit = photo.comments.length;            }            this.comments = photo.comments.slice(skip, limit);        }    }]);
复制代码

也就是,$stateParams不仅可以接收路由参数,还可以接收查询字符串参数。



photo-detail.html 需要把查询字符串参数传递出去

复制代码
<h1>photo-details</h1><a class="btn btn-default" ui-sref=".comment">通过相对路径去子state</a><a ui-sref="content.photos.list" style="margin-left: 15px;">  <i class="fa fa-arrow-circle-left fa-2x"></i></a><div ng-init="ctrPhotoDetail.init()">  <img class="img-responsive img-rounded" ng-src="../assets/images/{{ctrPhotoDetail.photo.imageName}}"       style="margin:auto; width: 60%;">  <div class="well well-sm" style="margin:auto; width: 60%; margin-top: 15px;">    <h4>{{ctrPhotoDetail.photo.title}}</h4>    <p>{{ctrPhotoDetail.photo.description}}</p>  </div>  <div style="margin:auto; width: 80%; margin-bottom: 15px;">    <button style="margin-top: 10px; width:100%;"            class="btn btn-default" ui-sref=".comment({skip:0, limit:2})">Comments</button>  </div></div><div ui-view></div>
复制代码

以上,通过ui-sref=".comment({skip:0, limit:2})把查询字符串传递出去。

 

photos-detail-comment.html

复制代码
<h1>photos-detail-comment</h1><div ng-init="ctrPhotoComment.init()" style="margin-top:15px;">  <div ng-repeat="comment in ctrPhotoComment.comments" class="well well-sm" style="margin: auto; width: 60%;">    <div class="media">      <div class="media-left media-middle">        <a href="">          <img class="img-circle" style="width:60px;" src="../assets/images/{{comment.imageName}}" alt="">        </a>      </div>      <div class="media-body">        <h4 class="media-heading">{{comment.name}}</h4>        {{comment.comment}}      </div>    </div>  </div></div>
复制代码

 

■ state间如何传递对象

通过data属性,把一个对象赋值给它。

 

复制代码
.state('content',{    url: '/',    abstract: true,    data:{        user: "user",        password: "1234"    },    views:{        "":{templateUrl: 'partials/content.html'},        "header@content":{templateUrl: 'partials/header.html'},    }})
复制代码

 

给header.html加上一个对应的控制器,并提供注销方法。

复制代码
$stateProvider    .state('content',{        url: '/',        abstract: true,        data:{            user: "user",            password: "1234"        },        views:{            "":{templateUrl: 'partials/content.html'},            "header@content":{                templateUrl: 'partials/header.html',                controller: function($scope, $rootScope, $state){                    $scope.logoff = function(){                        $rootScope.user = null;                    }                }            }        }    })
复制代码

 

添加一个有关登录页的state

复制代码
.state('content.login',{    url:'login',    data:{        loginError: 'User or password incorrect.'    },    views:{        "body@content" :{            templateUrl: 'partials/login.html',            controller: function($scope, $rootScope, $state){                $scope.login = function(user, password, valid){                    if(!valid){                        return;                    }                    if($state.current.data.user === user && $state.current.data.password === password){                        $rootScope.user = {                            name: $state.current.data.user                        }                        // Or Inherited                        /*$rootScope.user = {                            name: $state.$current.parent.data.user                        };*/                        $state.go('content.home');                                                }else{                        $scope.message = $state.current.data.loginError;                    }                }            }        }    }})
复制代码

 

添加login.html文件,现在的文件结构为:

asserts/
.....css/
.....images/
..........image1.jpg
..........image2.jpg
..........image3.jpg
..........image4.jpg
node_modules/
partials/
.....about.html
.....home.html
.....photos.html
.....content.html
.....header.html
.....photos-list.html
.....photo-detail.html
.....photos-detail-comment.html
.....login.html
app.js
index.html

login.html

复制代码
<form name="form" ng-submit="login(user, password, form.$valid)">    <div class="panel panel-primary" style="width:360px; margin: auto;">        <div class="panel-heading">            <h3 class="panel-title">Indentification</h3>        </div>        <div class="panel-body">            <input name="user" type="text" class="form-control" ng-model="user" placeholder="User ..." required>            <span ng-show="form.user.$error.required && form.user.$dirty" class="label label-danger">Enter the user</span>            <hr>            <input name="password" type="password" class="form-control" ng-model="password" placeholder="Password ..." required>            <span ng-show="form.password.$error.required && form.password.$dirty" class="label label-danger">Enter the password</span>                    </div>        <div class="panel-footer">            <button class="btn btn-default" type="submit">Login</button>            <button class="btn btn-default" type="reset">Reset</button>            <span class="label label-danger">{{message}}</span>                    </div>        </div></form>
复制代码

 

header.html 修改如下

复制代码
<nav class="navbar navbar-inverse">      <div class="container-fluid">        <div class="navbar-header">          <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">                        <span class="icon-bar"></span>            <span class="icon-bar"></span>            <span class="icon-bar"></span>          </button>          <a class="navbar-brand" ui-sref="content.home">Home</a>        </div>        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">          <ul class="nav navbar-nav">                <li>                    <a ui-sref="content.photos.list">Photos</a>                    </li>                <li>                    <a ui-sref="content.about">About</a>                    </li>           </ul>            <ul class="nav navbar-nav navbar-right">                                <li ng-if="user.name" class="dropdown">                    <a class="dropdown-toggle" role="button" aria-expanded="false" href="#" data-toggle="dropdown">{{user.name}} <span class="caret"></span></a>                    <ul class="dropdown-menu" role="menu">                        <li><a ui-sref="content.home" ng-click="logoff()">Sing out</a></li>                                            </ul>                                    </li>                                                <li ng-if="!user.name">                    <a ui-sref="content.login">Sing In</a>                </li>                                </ul>            </div>      </div>    </nav>
复制代码

 

■ onEnter和onExit事件

 

复制代码
.state('content.photos.detail',{    url: '/detail/:id',    templateUrl: 'partials/photos-detail.html',    controller: 'PhotoDetailController',    controllerAs: 'ctrPhotoDetail',    resolve:{        viewing: function($stateParams){            return{                photoId: $stateParams.id            }        }    },    onEnter: function(viewing){        var photo = JSON.parse(sessionStorage.getItem(viewing.photoId));        if(!photo){            photo = {                views: 1,                viewing: 1            }        }else{            photo.views = photo.views + 1;            photo.viewing = photo.viewing + 1;        }        sessionStorage.setItem(viewing.photoId, JSON.stringify(photo));    },    onExit: function(viewing){        var photo = JSON.parse(sessionStorage.getItem(viewing.photoId));        photo.viewing = photo.viewing - 1;        sessionStorage.setItem(viewing.photoId, JSON.stringify(photo));    }})
复制代码

 

在PhotoDetailController中:

复制代码
photoGallery.controller('PhotoDetailController', ['$scope', '$state', '$stateParams',    function($scope, $state, $stateParams){        var id = null;        this.photo = null;        this.viewObj = null;        this.init = function(){            id = parseInt($stateParams.id);            this.photo = $scope.ctrPhoto.photos[id];            this.viewObj = JSON.parse(sessionStorage.getItem($stateParams.id));        }    }]);
复制代码

 

photos-detail.html

复制代码
<h1>photo-details</h1><a class="btn btn-default" ui-sref=".comment">通过相对路径去子state</a><a ui-sref="content.photos.list" style="margin-left: 15px;">  <i class="fa fa-arrow-circle-left fa-2x"></i></a><div ng-init="ctrPhotoDetail.init()">  <img class="img-responsive img-rounded" ng-src="../assets/images/{{ctrPhotoDetail.photo.imageName}}"       style="margin:auto; width: 60%;">  <div class="well well-sm" style="margin:auto; width: 60%; margin-top: 15px;">    <div class="well well-sm pull-right" style="width: 100px;">      <i>Views <span class="badge">{{ctrPhotoDetail.viewObj.views}}</span></i>    </div>    <div class="well well-sm pull-right" style="width: 110px;">      <i>Viewing <span class="badge">{{ctrPhotoDetail.viewObj.viewing}}</span></i>    </div>    <h4>{{ctrPhotoDetail.photo.title}}</h4>    <p>{{ctrPhotoDetail.photo.description}}</p>  </div>  <div style="margin:auto; width: 80%; margin-bottom: 15px;">    <button style="margin-top: 10px; width:100%;"            class="btn btn-default" ui-sref=".comment({skip:0, limit:2})">Comments</button>  </div></div><div ui-view></div>
复制代码

 

■ StateChangeStart事件



controller.js 增加如下

复制代码
photoGallery.controller('RootController', ['$scope', '$state', '$rootScope',    function($scope, $state, $rootScope){        $rootScope.$on('$stateChangeStart',            function(event, toState, toParams, fromState, fromParams){                if(toState.data.required && !$rootScope.user){                    event.preventDefault();                    $state.go('content.login');                }            });    }]);
复制代码

 

修改content这个state:

复制代码
.state('content',{    url:'/',    abstract: true,    data:{        user: "user",        password: "1234"    },    views:{        "":{            templateUrl: 'partials/content.html',            controller: 'RootController'        },        "header@content":{            templateUrl: 'partials/header.html',            controller: function($scope, $rootScope, $state){                $scope.logoff = function(){                    $rootScope.user = null;                }            }        }    }})
复制代码

 

content.photos.detail这个state

复制代码
    .state('content.photos.detail',{        url:'/detail/:id',        templateUrl: 'partials/photos-detail.html',        controller: 'PhotoDetailController',        controllerAs: 'ctrPhotoDetail',        data:{            required: true        },        resolve:{            viewing: function($stateParams){                return{                    photoId: $stateParams.id                }            }        },        onEnter: function(viewing){                        var photo = JSON.parse(sessionStorage.getItem(viewing.photoId));            if(!photo){                photo = {                    views: 1,                    viewing: 1                }            }else{                photo.views = photo.views + 1;                photo.viewing = photo.viewing + 1;            }                        sessionStorage.setItem(viewing.photoId, JSON.stringify(photo));                    },        onExit: function(viewing){            var photo = JSON.parse(sessionStorage.getItem(viewing.photoId));            photo.viewing = photo.viewing - 1;            sessionStorage.setItem(viewing.photoId, JSON.stringify(photo));        }    })
复制代码

 

   
以上,添加了        
data:{
    required: true
}    


同理,content.photos.detail.comment这个state

 

复制代码
.state('content.photos.detail.comment',{        url:'/comment?skip&limit',        templateUrl: 'partials/photos-detail-comment.html',        controller: 'PhotoCommentController',        controllerAs: 'ctrPhotoComment',        data:{            required: true        }    })
复制代码

 


■ StateNotFound事件

 

复制代码
photosGallery.controller('RootController', ['$scope', '$state', '$rootScope',            function($scope, $state, $rootScope){                                $rootScope.$on('$stateChangeStart',                 function(event, toState, toParams, fromState, fromParams){                                        if(toState.data.required && !$rootScope.user){                        event.preventDefault();                        $state.go('content.login');                        return;                    }                                        });                                $rootScope.$on('$stateNotFound',                 function(event, unfoundState, fromState, fromParams){                    event.preventDefault();                    $state.go('content.notfound');                });            }]);
复制代码

 

添加一个state:

    .state('content.notfound',{        url:'notfound',        views: {            "body@content": {templateUrl: 'partials/page-not-found.html'}            }            })

 


page-not-found.html

<div class="well well-sm" style="margin: 20px;">    <i class="fa fa-frown-o fa-4x pull-left"></i><h3>404 - Sorry! Not found your page.</h3></div>

 

■ StateChangeSuccess事件

 

复制代码
photosGallery.controller('RootController', ['$scope', '$state', '$rootScope',            function($scope, $state, $rootScope){                                $rootScope.accessLog = new Array();                                $rootScope.$on('$stateChangeStart',                 function(event, toState, toParams, fromState, fromParams){                                        if(toState.data.required && !$rootScope.user){                        event.preventDefault();                        $state.go('content.login');                        return;                    }                                        });                                $rootScope.$on('$stateNotFound',                 function(event, unfoundState, fromState, fromParams){                    event.preventDefault();                    $state.go('content.notfound');                });                                $rootScope.$on('$stateChangeSuccess',                 function(event, toState, toParams, fromState, fromParams){                    $rootScope.accessLog.push({                        user: $rootScope.user,                        from: fromState.name,                        to: toState.name,                        date: new Date()                    });                });                            }]);
复制代码

 

添加一个state

复制代码
    .state('content.log',{        url:'log',        data:{            required: true        },        views: {            "body@content": {templateUrl: 'partials/log.html'}            }            })
复制代码

 

log.html

复制代码
<h1><i class="fa fa-file-text-o"></i> Access Log</h1><div style="margin:auto; width: 380px;">    <div class="well well-sm" ng-repeat="log in accessLog track by $index">        <i class="fa fa-pencil fa-2x pull-left"></i>        {{log.user ? log.user.name: 'anonymous'}} in {{log.date | date: 'longDate'}} at {{log.date | date: 'shortTime'}}        <p>From: {{log.from}} => to: {{log.to}}</p>    </div></div>
复制代码

 


■ StateChangeError事件

 

复制代码
photosGallery.controller('RootController', ['$scope', '$state', '$rootScope',            function($scope, $state, $rootScope){                                $rootScope.accessLog = new Array();                                $rootScope.$on('$stateChangeStart',                 function(event, toState, toParams, fromState, fromParams){                                        if(toState.data.required && !$rootScope.user){                        event.preventDefault();                        $state.go('content.login');                        return;                    }                                        });                                $rootScope.$on('$stateNotFound',                 function(event, unfoundState, fromState, fromParams){                    event.preventDefault();                    $state.go('content.notfound');                });                                $rootScope.$on('$stateChangeSuccess',                 function(event, toState, toParams, fromState, fromParams){                     $rootScope.accessLog.push({                         user: $rootScope.user,                         from: fromState.name,                         to: toState.name,                         date: new Date()                     });                });                                $rootScope.$on('$stateChangeError',                 function(event, toState, toParams, fromState, fromParams, error){                    event.preventDefault();                    $state.go('content.error', {error: error});                });                            }]);
复制代码

 

添加2个state:

复制代码
    .state('content.profile', {        url:'profile',        data:{            required: true        },        resolve:{            showError: function(){                throw 'Error in code.';            }        },        views:{            "body@content": {template: '<div>Error</div>'}        }        })     .state('content.error',{        url:'error/:error',        views:{            "body@content":{                templateUrl: 'partials/error.html',                controller: function($scope, $stateParams){                    $scope.error = {                        message: $stateParams.error                    }                }            }        }    })   
复制代码

 

error.html

<div class="well well-sm" style="margin: 20px;">    <i class="fa fa-exclamation-circle fa-2x"> Sorry! But this message was displayed: {{error.message}}</i></div>

 

0 0
原创粉丝点击