AngularJS 进阶
依赖注入
依赖注入方式
- 内部创建依赖;
- 通过全局变量进行引用;
- 在需要的地方通过参数进行传递。
前两种方式都不是很好,因为都需要依赖硬编码,使得修改、测试的时候会很麻烦。
第三种方式是最好的实现方式,因为它不必在组件中主动查找和获取依赖,而是由外界传入。
AngularJS注入内容(服务)到函数中都是通过函数参数的方法,有三种方式:
- 推断式注入声明;
- 显示注入声明;
- 行内注入声明;
推断式注入声明
直接将要注入内容的名字写在函数参数中,名字必须准确。
建议:不要使用这种方式。因为大部分情况下,代码到生产环境时,都会打包压缩,变量名称会简化,如果名称变化可能就会找不到依赖。
app.controller("myController", function ($scope, $filter) {
$scope.showId = 1;
});
显示注入声明
通过设置函数对象的$inject属性来实现显示注入声明的功能。
$inject属性是一个数据,数组的每个元素都是字符串,每个字符串代表了所要依赖的内容名字。
数组中字符串顺序必须和函数参数顺序相同。
函数参数名字可以随意修改,但数组中字符串必须是依赖内容的名字。
这种注入方式解决了推断式注入的压缩问题。因为压缩不能改变数组内容,而AngularJS通过数组内容查找依赖。
语法:
var myController = function(rename$scope, renameGreeter) {...}
myController.$inject = ["$scope", "greeter"]; // 这里数组内必须准确
行内注入声明
在调用方法定义一个控制器(服务、指令等)时,可以通过传入一个数组参数,而不是一个函数。数组的最后一个元素是函数,前面的元素都是这个函数要依赖内容的名字(字符串类型),函数参数与前面的元素一一对应。
语法结构:
app.controller("myController", ["$scope", "$filter", function ($scope, $filter) {
$scope.showId = 1;
}]);
服务
服务是什么
服务就是一个函数或对象。
服务的作用
AngularJS的服务能在应用的整个生命周期内保存数据;
AngularJS的服务保证一份数据在整个应用中的一致性,比如:sessionid要求全局都是一份;
AngularJS的服务是各个控制器间通信的桥梁;
将多个控制器中的相似代码抽取出来定义一个服务,可以减少代码量,提高代码的可维护性。
如何使用服务
通过依赖注入方式将服务注入到函数中,就可以在函数中使用服务。
内置服务和自定义服务使用方式没有区别。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app = angular.module("app", []);
// 通过依赖注入的方式,引入服务
app.controller("myController", ["$scope", "$filter", function ($scope, $filter) {
$scope.date = $filter("date")(new Date(), "yyyy-MM-dd");
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
{{date}}
</div>
</div>
</body>
</html>
service创建方法
AngularJS提供了5种创建服务的方法:factory、service、constat、value、provider。
这个5种方法都是定义在模块实例上的,因此都是通过模块实例调用的。
通过依赖其他模块,可以使用其他模块上定义的服务。
factory
语法: app.factory(name, getFn);
参数说明:
- name:服务名。
- getFn:实例服务的函数,其返回值可以是函数、对象、简单类型等任意类型数据。
注意:AngularJS的服务都是单实例,即getFn函数在应用的整个生命周期内只会调用一次。
当服务第一次注入到控制器或指令等时,AngularJS会自动调用getFn实例化服务,该实例会保存在AngularJS的缓存对象中,等有其他地方调用服务时,首先会判断缓存对象中是否存在,不存在再去实例化。
示例1:
(1)展示factory定义服务的方法;
(2)通过打印日志,说明多个控制器注入,服务也只会被实例化一次;
(3)各个控制器可以通过服务进行通信。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app = angular.module("app", []);
app.factory("nameService", function () {
console.log("init nameService");
var name = "张三";
return {
getName: function () {
return name;
},
setName: function (newName) {
name = newName;
}
}
});
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
// controller1通过服务获取name,然后再修改name
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
// controller2通过服务获取的是修改后的name
$scope.name2 = nameService.getName();
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
示例2: 该示例主要说明通过模块依赖,可以使用其它模块定义的服务。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.factory("nameService", function () {
console.log("init nameService");
var name = "张三";
return {
getName: function () {
return name;
},
setName: function (newName) {
name = newName;
}
}
});
// app依赖于app1,可以使用app1上定义的服务
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
$scope.name2 = nameService.getName();
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
service
语法:app.service(name, getFn);
参数说明:
name:服务名。
getFn:实例服务的构造函数。
service和factory创建服务的特性都是一样的,只是创建的方式不一样。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.service("nameService", function () {
console.log("init nameService");
var name = "张三";
return {
getName: function () {
return name;
},
setName: function (newName) {
name = newName;
}
}
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
$scope.name2 = nameService.getName();
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
provider
语法:app.provider(name, getFn or Object);
参数说明:
name:服务名。
getFn or Object:可以是函数或对象。如果是函数,这个函数是一个构造函数,构造函数必须由
g
e
t
属
性
,
这
个
属
性
是
一
个
方
法
,
有
返
回
值
;
如
果
是
对
象
,
也
必
须
有
get属性,这个属性是一个方法,有返回值;如果是对象,也必须有
get属性,这个属性是一个方法,有返回值;如果是对象,也必须有get属性,与函数中
g
e
t
一
样
。
当
服
务
注
入
到
控
制
器
时
,
A
n
g
u
l
a
r
J
S
会
调
用
get一样。 当服务注入到控制器时,AngularJS会调用
get一样。当服务注入到控制器时,AngularJS会调用get方法创建服务实例。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.provider("nameService", function () {
var self = this;
self.name = "张三";
self.setName = function (newName) {
self.name = newName;
};
self.getName = function () {
return self.name;
};
self.$get = function () {
console.log("init nameService");
return {
getName: self.getName,
setName: self.setName
}
}
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
$scope.name2 = nameService.getName();
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
通过对象形式定义:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.provider("nameService", {
name: "张三",
$get: function () {
var self = this;
return {
getName: function () {
return self.name;
},
setName: function (newName) {
self.name = newName
}
}
}
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
$scope.name2 = nameService.getName();
}]);
app.config(function (nameServiceProvider){
console.log("config begin");
nameServiceProvider.$get().setName("哈哈哈");
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
factory、service、provider三种方法的区别和联系:
factory实际也是调用provider实现的服务;而service是调用factory。
provider创建的服务功能更加强大,可以通过app.config(function(服务名Provider){…}),提前设置provider服务的属性名。
app.config方法是在所有服务实例化前执行的,比如:如果通过服务控制国际化,那么就需要在所有服务实例化之前进行国际化的配置。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.provider("nameService", function () {
var self = this;
self.name = "张三";
self.setName = function (newName) {
self.name = newName;
};
self.getName = function () {
return self.name;
};
self.$get = function () {
console.log("init nameService");
return {
getName: self.getName,
setName: self.setName
}
}
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.getName();
nameService.setName("李四");
}]);
app.controller("controller2", ["$scope", "nameService", function ($scope, nameService) {
$scope.name2 = nameService.getName();
}]);
app.config(function (nameServiceProvider){
console.log("config begin");
// 服务实例化之前,设置provider服务的属性
nameServiceProvider.setName("哈哈哈");
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
<div ng-controller="controller2">
hello {{name2}}
</div>
</div>
</body>
</html>
使用场景建议:
(1)当希望在应用开始前对服务进行配置的时候需要使用provider()。比如,我们需要配置服务在不同的部署环境里面(开发,演示,生产)使用不同的后端进行处理的时候,或者国际化选择的时候。
(2)factory和service两个基本一致,可以随意使用。
value
语法:app.value(name, value); 实际上最终还是调用的factory实现的。
参数说明:
name:服务名;
value:任意值;
**功能:**定义一个常量值服务,依赖注入后,就可以拿到这个常量值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.value("nameService", {
name: "张三"
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.name;
}]);
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
</div>
</body>
</html>
constant
语法:app.constant(name, value);
参数说明:
name:服务名。
value:任意值。
功能:定义一个常量值服务,通过依赖注入拿到这个常量值。
实现上与value创建的常量服务有所区别,constant是将常量值直接放入了缓存对象中,所以可以通过app.config拿到,而value不行(使用factory创建的)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript">
var app1 = angular.module("app1", []);
app1.constant("nameService", {
name: "张三"
});
var app = angular.module("app", ["app1"]);
app.controller("controller1", ["$scope", "nameService", function ($scope, nameService) {
$scope.name1 = nameService.name;
}]);
// config获取constant服务就是名称,没有后缀
app.config(function (nameService) {
console.log(nameService.name);
})
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controller1">
hello {{name1}}
</div>
</div>
</body>
</html>
内置服务
$filter, $animate, $http等
详情参考:link
路由
SPA—单页面应用
SPA(single page application)是值浏览器只在初始时加载一次HTML页面,后面所有的操作知识改变视图的部分内容,不会重新加载整个HTML页面。
与后端交互一般是通过ajax实现的;
视图切换时通过路由实现的。
单页面应用中url地址的#是什么
单页面视图特点:url地址中锚部分(#开始)改变不会重新加载整个html页面,但是通过路由可以改变视图部分内容。
AngularJS实现单页面
实现SPA的核心:实现页面视图部分的切换,在AngularJS中,可以通过ngRouter和uiRouter两种方式实现SPA的视图切换。
ngRoute
ngRoute是什么
ngRoute是一个angularJS模块,主要用于路由控制,需要单独引入。
ngRoute是一种路由控制机制,核心原理是:当请求一个url时,根据路由配置匹配这个url,然后请求模板片段,并插入到ng-view指令所在的DOM中。
ngRoute核心内容
ngRoute模块包含以下内容:
ngView:提供不同路由模板插入的视图层。
$routerProvider:提供路由配置。
$router:用于构建各个路由的url、view、controller。
$routerParams:解析返回路由中带有的参数。
ui-router
ui-router是什么
ui-router是一个angularJS模块。
ui-router是Angular-UI提供的客户端路由框架。
ui-router核心内容
ui-view:提供不同路由模板插入的视图层;
ui-sref:将当前DOM连接到特定状态;
ui-sref-active:给所在DOM添加激活状态;
$stateProvider:状态配置;
$state:状态服务,提供状态判断、跳转等;
$stateParams:路由参数服务;
$urlRouterProvider: 提供特定URL被激活时处理机制。
ui-router基本用法
- 在主模板中使用ui-view定义一个状态模板视图层,不同状态对应的模板将会插入到这个ui-view指令所在的DOM元素中。
- 使用$stateProvider进行路由配置,包括每个状态对应的name、url、template以及controller。除了这些基本配置外,还会有一些额外配置,比如resolve配置等。
- 在每个路由的controller中完成对应的业务逻辑。
- 可以通过注入 s t a t e P a r a m s 服 务 获 取 状 态 上 配 置 的 参 数 , 还 可 以 通 过 stateParams服务获取状态上配置的参数,还可以通过 stateParams服务获取状态上配置的参数,还可以通过scope监控 s t a t e C h a n g e S t a r t 和 stateChangeStart和 stateChangeStart和stateChangeSuccess等事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
// 依赖注入ui.router
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home", {url: "/home", template: "这是Home"});
$stateProvider.state("view1", {url: "/view1", template: "这是view1"});
$stateProvider.state("view2", {url: "/view2", template: "这是view2"});
});
</script>
</head>
<body>
<div ng-app="app">
<span ui-sref="home">Home</span>
<span ui-sref="view1">view1</span>
<span ui-sref="view2">view2</span>
<div ui-view></div>
</div>
</body>
</html>
ui-router和ngRoute的区别
ui-router提供了ngRoute的全部功能。
ui-router解决了ngRoute一些不足:
- 视图不能嵌套,这意味着$scope会发生不必要的重新载入。
- 同一URL下不支持多个视图。这一需求也是常见的:我们希望导航栏用一个视图(和相应的控制器)、内容部分用另一个视图(和相应的控制器)。
ngRoute和ui-route核心内容对比:
$route —> $state
$routeParams —> $stateParams
$routeProvider —> $stateProvider
uiView
uiView是angularJS的指令。
用法:
- ,ui-view没有指定视图名时,各个状态对应的视图都是呈现在这个地方,即各个状态的template插入的地方。
- ,指定了视图名称,用于一个状态(一个URL)对应多个视图。
uiView可以嵌套;
一个状态可以对应多个视图。
示例:状态对应多个视图。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
views: {
leftView: {
template: "这是Home页面的left视图"
},
rightView: {
template: "这是Home页面的right视图"
}
}
});
$stateProvider.state("view1",
{
url: "/view1",
views: {
leftView: {
template: "这是view1页面的left视图"
},
rightView: {
template: "这是view1页面的right视图"
}
}
});
$stateProvider.state("view2",
{
url: "/view2",
views: {
leftView: {
template: "这是view2页面的left视图"
},
rightView: {
template: "这是view2页面的right视图"
}
}
});
});
</script>
<style>
.view {
border: 1px solid red;
display: inline-block;
width: 45%;
height: 500px;
}
</style>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home">Home</span>
<span ui-sref="view1">view1</span>
<span ui-sref="view2">view2</span>
</div>
<div class="view" ui-view="leftView"></div>
<div class="view" ui-view="rightView"></div>
</div>
</body>
</html>
ui-sref
作用:绑定ui-sref指令所在DOM到一个状态,当点击这个DOM时,会跳转到对应状态。
用法:
(1)ui-sref=“stateName”
(2)ui-sref=“stateName({param:value, param:value})”,可以传递参数给对应的状态,可以通过
s
t
a
t
e
P
a
r
a
m
s
服
务
拿
到
对
应
的
状
态
。
∗
∗
注
意
∗
∗
:
参
数
属
性
名
必
须
在
状
态
配
置
项
p
a
r
a
m
s
中
定
义
,
否
则
无
法
生
效
。
u
i
−
s
r
e
f
功
能
和
stateParams服务拿到对应的状态。 **注意**:参数属性名必须在状态配置项params中定义,否则无法生效。 ui-sref功能和
stateParams服务拿到对应的状态。∗∗注意∗∗:参数属性名必须在状态配置项params中定义,否则无法生效。ui−sref功能和state.go(“stateName”)类似,只是一个用在HTML中,一个用在js中。
示例:ui-sref传递参数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
// 必须要在params中定义id属性,否则传入的参数不会加入到$stateParams服务中
params: {
id: 0
},
controller: function($scope, $stateParams){
console.log($stateParams);
},
template: "这是view1页面的视图"
});
$stateProvider.state("view2",
{
url: "/view2",
template: "这是view2页面的视图"
});
});
</script>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home">Home</span>
<span ui-sref="view1({id: 10})">view1</span>
<span ui-sref="view2">view2</span>
</div>
<div class="view" ui-view></div>
</div>
</body>
</html>
ui-sref-active
作用:给ui-sref-active指令所在DOM元素添加状态激活样式,当状态不激活时,样式类自动去掉。
用法:ui-sref-active=“class1 class2”
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
template: "这是view1页面的视图"
});
$stateProvider.state("view2",
{
url: "/view2",
template: "这是view2页面的视图"
});
});
</script>
<style>
.active {
color: red;
}
</style>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home" ui-sref-active="active">Home</span>
<span ui-sref="view1" ui-sref-active="active">view1</span>
<span ui-sref="view2" ui-sref-active="active">view2</span>
</div>
<div class="view" ui-view></div>
</div>
</body>
</html>
$stataProvider
s
t
a
t
e
P
r
o
v
i
d
e
r
是
一
个
对
象
。
u
i
.
r
o
u
t
e
r
模
块
通
过
p
r
o
v
i
d
e
r
方
法
定
义
了
stateProvider是一个对象。 ui.router模块通过provider方法定义了
stateProvider是一个对象。ui.router模块通过provider方法定义了state服务,因此可以再config方法中配置
s
t
a
t
e
。
在
配
置
函
数
中
就
是
通
过
state。在配置函数中就是通过
state。在配置函数中就是通过stateProvider调用state方法配置状态的。
$stateProvider提供了两个方法:一个是state方法用于配置状态,另一个是decorator方法用于获取或者重定义状态配置。
用法:$stateProvider.state(“stateName” , stateConfig);
stateConfig
stateName
类型:String
作用:定义状态的名字。
说明:可以通过小数点方式定义嵌套状态(有父子关系的状态)。例如:“contacts.list”。
示例:嵌套路由。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
// 如果加上otherwise,就会导致默认打开/program;如果是多个页签,可以选择默认打开某个页签。
// $urlRouterProvider.otherwise("/program");
$stateProvider.state("program",
{
url: "/program",
template: "<p ui-sref='program.list'>编程语言:</p><div ui-view></div>",
controller: function ($scope) {
$scope.tools = ["python", "java", "js"]
}
});
$stateProvider.state("program.list",
{
url: "/list",
// 这里子路由中可以直接使用父作用域的数据
template: "<ul><li ng-repeat='tool in tools'>{{tool}}</li></ul>"
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ui-sref="program">编程:</div>
<div ui-view></div>
</div>
</body>
</html>
template,templateUrl,templateProvider
这三个都是定义状态对应的模板。
(1) template:
类型:String 或 function。
说明:函数必须返回一个字符串,函数有一个$stateParams参数。
(2) templateUrl:
类型:String 或 function。
说明:函数必须返回一个字符串,字符串内容是一个Url,函数有一个$stateParams参数。
(3) templateProvider:
类型:function。
说明:函数必须返回一个字符串,字符串内容是一个url。与前两种函数方式区别:该方法可以给函数注入angularJS服务。
controller,controllerProvider
这两个都是定义状态对应的控制器。
(1)controller:
类型:String 或 function。
说明:String内容是当前模板上已经定义好一个控制器名;如果是函数,类似于controller方法的第二个参数,定义一个控制器。
(2)controllerProvider:
类型:function。
说明:函数必须返回一个字符串(控制器名称),或返回一个函数(定义控制器的函数)。controllerProvider提供了一种可以根据业务逻辑动态添加控制器的方法。
示例参考stateName中的示例,定义了控制器。
resolve
如果需要给状态controller注入一些该状态自己的函数或数据,可以通过resolve实现。
类型:Object
说明: 对象的每个属性都是要注入controller的依赖。属性值可以是一个字符串,也可以是一个函数。
(1)如果属性值是String,该字符串是一个该模块上已经注册的服务名;
(2)如果值是一个函数,则注入这个函数,函数的返回值就是依赖。如果函数返回一个promise,它会在控制器被实例化之前resolved,同时其返回值会注入到控制器中。
关于$q和promise:link
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
// 如果加上otherwise,就会导致默认打开/program
// $urlRouterProvider.otherwise("/program");
$stateProvider.state("program",
{
url: "/program",
template: "<ul><li ng-repeat='tool in tools'>{{tool}}</li></ul>",
resolve: {
tools: function ($q, $timeout) {
var defer = $q.defer();
$timeout(function () {
// 1s后执行resolve,resolve的参数会作为promise执行成功的入参
defer.resolve(["python", "java", "js"]);
}, 1000);
// 返回一个promise对象
return defer.promise
},
id: function () {
return 100
}
},
controller: function ($scope, tools, id) {
$scope.tools = tools;
$scope.id = id;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ui-sref="program">编程:</div>
<div ui-view></div>
</div>
</body>
</html>
url
类型:String
功能:给状态分配一个url。用户可以再浏览器中输入url,跳转到对应的视图。
说明:改参数设置的是一个完整url的锚部分,即#号后面的内容。还可以在url中设置参数,参数会存在$stateParams服务中。
例如1: url: “/contacts/:contactId”
例如2: url: “/view1/{viewId:.*}”
作用:可以将一个状态和多个url匹配。
示例:传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
// 如果加上otherwise,就会导致默认打开/program
// $urlRouterProvider.otherwise("/program");
$stateProvider.state("program",
{
url: "/program:id",
template: "<div>这是第{{id}}条数据</div>",
controller: function ($scope, $stateParams) {
$scope.id = $stateParams.id;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ui-sref="program">编程:</div>
<div ui-view></div>
</div>
</body>
</html>
params
类型:Object
功能:设置该状态参数,状态激活时,这些参数被放到
s
t
a
t
e
P
a
r
a
m
s
服
务
中
,
因
此
,
我
们
在
状
态
控
制
器
中
通
过
注
入
stateParams服务中,因此,我们在状态控制器中通过注入
stateParams服务中,因此,我们在状态控制器中通过注入stateParams服务使用这些参数。
说明:不要和url一起使用,因为url也可以定义参数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
// 必须要在params中定义id属性,否则传入的参数不会加入到$stateParams服务中
params: {
id: 0
},
controller: function($scope, $stateParams){
console.log($stateParams);
},
template: "这是view1页面的视图"
});
});
</script>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home">Home</span>
<span ui-sref="view1({id: 10})">view1</span>
</div>
<div class="view" ui-view></div>
</div>
</body>
</html>
views
类型:对象。
功能:设置一个状态对应多个视图。
用法:{viewName: viewConfig…}
viewConfig:视图配置对象,与$stateProvider.state(name,stateConfig),第二个参数类似。
说明:
(1)每个视图模板会放入页面中的ui-view=viewName所在的DOM中。
(2)设置了view后,template、templateUrl、templateProvider将被忽略。
示例:状态对应多个视图。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
views: {
leftView: {
template: "这是Home页面的left视图"
},
rightView: {
template: "这是Home页面的right视图"
}
}
});
$stateProvider.state("view1",
{
url: "/view1",
views: {
leftView: {
template: "这是view1页面的left视图"
},
rightView: {
template: "这是view1页面的right视图"
}
}
});
$stateProvider.state("view2",
{
url: "/view2",
views: {
leftView: {
template: "这是view2页面的left视图"
},
rightView: {
template: "这是view2页面的right视图"
}
}
});
});
</script>
<style>
.view {
border: 1px solid red;
display: inline-block;
width: 45%;
height: 500px;
}
</style>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home">Home</span>
<span ui-sref="view1">view1</span>
<span ui-sref="view2">view2</span>
</div>
<div class="view" ui-view="leftView"></div>
<div class="view" ui-view="rightView"></div>
</div>
</body>
</html>
abstract
类型:Boolean
默认值:false
功能:设置当前状态为抽象状态,抽象状态不能被点击直接激活。但是其子状态不受影响,可以被激活,如果子状态被激活,父状态也会一起激活。
说明:抽象状态一般主要用于为所有子状态提供一个公共性的东西。例如:使子状态的url都在一个父url下,所有子状态公用一段DOM时;所有子状态公用一个$scope时。
onEnter,onExit
类型:function
功能:进入状态或离开状态是调用的函数。
说明:这两个函数可以获得resolve定义的所有依赖。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
template: "这是view1页面的视图",
onEnter: function () {
console.log("onEnter");
},
onExit: function () {
console.log("onExit");
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div>
<span ui-sref="home">Home</span>
<span ui-sref="view1">view1</span>
</div>
<div class="view" ui-view></div>
</div>
</body>
</html>
date
类型:对象。
功能:给状态配置对象添加数据,主要用于向子状态传递数据。
说明:与resolve的功能类似,但是data不会被注入到控制器中,定义的promise也不会被resolve。
state
$state是定义在ui.router模块上的AngularJS服务。
ui.router通过provider定义了该服务,因此可以通过config方法配置该服务。
$state服务提供了很多非常有用的方法可以对状态进行控制。
$state服务通过依赖注入使用。
go()方法
语法:$state.go(toState, [,toParams][,options])
执行这个代码后,状态就会跳转到toState。
toState参数可以设置绝对路径或相对路径。以^和.开始就是相对路径,其他都是绝对路径。
例如:
$state.go(“contact.detail”) 会跳转到contact.detail状态
$state.go("^") 会跳转到父状态
$state.go("^.siblingName") 会跳转到siblingName状态
$state.go(".childName") 会跳转到childName状态
示例:绑定ng-click事件,在点击事件中通过$state.go跳转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.controller("myController", ["$scope", "$state", function ($scope, $state) {
$scope.homeFun = function () {
$state.go("home");
};
$scope.view1Fun = function () {
$state.go("view1", {greeting: "hello view1"});
}
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
params: {
greeting: ""
},
template: "这是view1页面的视图:{{greeting}}",
controller: function ($scope, $stateParams) {
$scope.greeting = $stateParams.greeting;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
<span ng-click="homeFun()">Home</span>
<span ng-click="view1Fun()">view1</span>
</div>
<div ui-view></div>
</div>
</body>
</html>
reload()方法
语法:$state.reload()。
执行后当前状态会被重新加载。Resolve被重新resolved,controller重新实例化,但是状态事件不会被重新触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.controller("myController", ["$scope", "$state", function ($scope, $state) {
$scope.homeFun = function () {
$state.go("home");
};
$scope.view1Fun = function () {
$state.go("view1", {greeting: "hello view1"});
};
$scope.reloadFun = function () {
$state.reload();
}
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
params: {
greeting: ""
},
template: "这是view1页面的视图:{{greeting}}",
controller: function ($scope, $stateParams) {
$scope.greeting = $stateParams.greeting;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
<span ng-click="homeFun()">Home</span>
<span ng-click="view1Fun()">view1</span>
<span ng-click="reloadFun()">重新加载当前状态</span>
</div>
<div ui-view></div>
</div>
</body>
</html>
includes()方法
语法:$state.includes(stateName[, params])。
返回值:boolean。
判断当前激活状态是否是statName状态或子状态。如果传入了第二个参数params,那么将一块对比params,如果全部相同,返回true,否则返回false。
is()方法
语法:$state.is(stateName[, params])。
返回值:boolean。
判断当前激活状态是否是statName状态。如果传入了第二个参数params,那么将一块对比params,如果全部相同,返回true,否则返回false。
href()方法
语法:$state.href(stateName[, params][, options])。
返回值:String。
获取stateOrName对应状态激活时的url值。
get()方法
语法:$state.get(stateName)。
返回值:Object or Array。
有参数时:获取参数对应状态时配置参数;没有参数时,获取注册的所有状态对应的配置对象数组。
current
语法:$state.current。
返回值:Object。
获取当前激活状态对应的配置对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.controller("myController", ["$scope", "$state", function ($scope, $state) {
$scope.homeFun = function () {
$state.go("home");
};
$scope.view1Fun = function () {
$state.go("view1", {greeting: "hello view1"});
};
$scope.getFun = function () {
console.log($state.includes("view1"));
console.log($state.is("view1"));
console.log($state.href("view1"));
console.log($state.get());
console.log($state.current);
}
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
params: {
greeting: ""
},
template: "这是view1页面的视图:{{greeting}}",
controller: function ($scope, $stateParams) {
$scope.greeting = $stateParams.greeting;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
<span ng-click="homeFun()">Home</span>
<button ng-click="getFun()">获取状态信息</button>
</div>
<div ui-view></div>
</div>
</body>
</html>
$stateParams
$stateParams是定义在ui-router模块上的AngularJS服务。
$stateParams主要用于保存当前激活状态对应的参数。可以设置参数的地方有:url属性、params属性。
$stateParams服务通过依赖注入方式使用。
$urlRouterProvider
$urlRouterProvider是一个对象。
u
r
l
R
o
u
t
e
r
P
r
o
v
i
d
e
r
是
通
过
p
r
o
v
i
d
e
r
定
义
在
u
i
−
r
o
u
t
e
r
模
块
上
的
A
n
g
u
l
a
r
J
S
服
务
。
因
此
,
可
以
再
c
o
n
f
i
g
配
置
函
数
中
设
置
urlRouterProvider是通过provider定义在ui-router模块上的AngularJS服务。因此,可以再config配置函数中设置
urlRouterProvider是通过provider定义在ui−router模块上的AngularJS服务。因此,可以再config配置函数中设置urlRouterProvider。
$urlRouterProvider定义了三个方法:when()、otherwise()、rule()。
when()
$urlRouterProvider.when(whenUrlPath, toUrlPath)
功能:重定向url地址。
参数:whenPath是想要匹配的入口路径,toPath是要重定向的路径。
otherwise()
$urlRouterProvider.otherwise(urlPath)
功能:没有找到匹配的路径时,重定向到Path路径。主要用于设置默认路径。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.controller("myController", ["$scope", "$state", function ($scope, $state) {
$scope.homeFun = function () {
$state.go("home");
};
$scope.view1Fun = function () {
$state.go("view1", {greeting: "hello view1"});
};
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
// 非法路由跳转到/view1
$urlRouterProvider.otherwise("/view1");
// /home重定向到/view1
$urlRouterProvider.when("/home", "/view1");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
params: {
greeting: ""
},
template: "这是view1页面的视图:{{greeting}}",
controller: function ($scope, $stateParams) {
$scope.greeting = $stateParams.greeting;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
<span ng-click="homeFun()">Home</span>
<button ng-click="view1Fun()">View1</button>
</div>
<div ui-view></div>
</div>
</body>
</html>
ui-router事件
ui-router中事件主要分状态改变事件和视图加载事件。
所有事件都是从
r
o
o
t
S
c
o
p
e
上
开
始
广
播
的
,
因
此
,
在
所
有
的
rootScope上开始广播的,因此,在所有的
rootScope上开始广播的,因此,在所有的scope上都能监听这些事件。
状态改变事件:
(1) $stateChangeStart:状态跳转开始时触发事件
(2) $stateChangeSuccess:状态跳转成功时触发事件
(3) $stateChangeErrot:状态跳转失败时触发事件
(4) $stateNotFound:没找到对应状态时触发事件
视图加载事件:
(1) $viewContentLoading:视图开始加载时,DOM被渲染前触发事件
(2) $viewContentLoaded:视图加载完成时,DOM被渲染完成后触发事件
事件监听方法:
s
c
o
p
e
.
scope.
scope.on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams, options){…});
s
c
o
p
e
.
scope.
scope.on("$stateNotFound", function(event, toState, toParams, fromState, fromParams, options){…});
s
c
o
p
e
.
scope.
scope.on("$viewContentLoading", function(event, toState, toParams, fromState, fromParams, options){…});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="lib/angular.min.js"></script>
<script type="application/javascript" src="lib/angular-ui-router.js"></script>
<script type="application/javascript">
var app = angular.module("app", ["ui.router"]);
app.controller("myController", ["$scope", "$state", "$rootScope", function ($scope, $state, $rootScope) {
$scope.homeFun = function () {
$state.go("home");
};
$scope.view1Fun = function () {
$state.go("view1", {greeting: "hello view1"});
};
$scope.$on("$stateChangeStart", function(event, toState) {
console.log("$stateChangeStart:" + toState.name);
});
$scope.$on("$stateChangeSuccess", function(event, toState) {
console.log("$stateChangeSuccess:" + toState.name);
});
$scope.$on("$stateNotFound", function(event, unfoundState, fromState) {
console.log("$stateNotFound:" + unfoundState.to);
});
$scope.$on("$viewContentLoading", function(event, viewConfig) {
console.log("$viewContentLoading.");
});
$scope.$on("$viewContentLoaded", function(event, viewConfig) {
console.log("$viewContentLoaded.");
})
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider.state("home",
{
url: "/home",
template: "这是Home页面的视图"
});
$stateProvider.state("view1",
{
url: "/view1",
params: {
greeting: ""
},
template: "这是view1页面的视图:{{greeting}}",
controller: function ($scope, $stateParams) {
$scope.greeting = $stateParams.greeting;
}
});
});
</script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myController">
<span ng-click="homeFun()">Home</span>
<button ng-click="view1Fun()">View1</button>
<div ui-view></div>
</div>
</div>
</body>
</html>