而且module中需要加入
var app = angular.module('MyApp',['ngRoute',...]);
var app = angular.module('MyApp',['ui.router',...]);
到目前为止,我学习的都是单个html页面view,如果页面复杂了呢?这时候我们就要引入路由(route)了;angular tutorial中的phone例子,可以将index.html变成一个"layout template",这个模板由所有的views共用,其他的patial templates则依据当前route填充进layout template展现给用户~
路由简介:
由$routeProvider声明,由$route service提供,它把controller,view templates和浏览器中的当前url location串联到一起;使用这个特性,我们可以实现浏览器历史等功能。
notice
angular js 从1.0.x 到 1.2.x版本,使用ngRoute需要引入angular-route.js
而且module中需要加入
var app = angular.module('MyApp',['ngRoute',...]);
var app = angular.module('MyApp',['ui.router',...]);
dependency injection
依赖注入是angular js的核心。
有三种方法可以让一个component获取它的依赖。
1.component内部新建dependency,很多都使用new operator。
2.componet通过获取全局依赖变量。
3.作为参数传递给component。
前两种耦合性太强,所以angular js 使用了第三种作为依赖注入~ 可以注入angular 中自带的 $routeProvider $scope等,也可以自己定义provider和service注入。
++路由的使用方法即为 在config中声明$routeProvider,在controller中注入$route 这个service。
provider 和 service之间的关系是这样的,provider is like factory, 它创建了一个service,在config中声明$routeProvider.when等,相当于对$route这个service进行了初始化操作,
如果将初始化代码移动到ctrl中,则path更改也无法路由,无法生效。
template - ng-view
$route service通常和ng-view,$routeParams一起使用.
layout template
<body ng-app="phonecatApp">
<div ng-view></div>
</body>
controller
var phonecatApp = angular.module('phonecatApp', [
'ngRoute',
'phonecatControllers'
]);
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
when('/phones')
: 当 URL hash fragment match /phones,会显示 phone list view,匹配 PhoneListCtrl 这个controller.
when('/phones/:phoneId')
: 当URL hash fragment matches '/phones/:phoneId'的时候,phone-detail view就会显现,:phoneId
就是一个$routeParams的子元素,在PhoneDetailCtrl中可以通过$routeParams.phoneId获取其值.
otherwise({:'/phones'})
: 如果url无法match上面两种情况,就会进入/phone,即显示phone-list view.
说到redirect, 除可以简单的redirect到上面的when后缀,可以写function写逻辑~
.when("pizza/:crust/:toppings',{
redirectTo: function(routeParams,path,search){
console.log(routeParams)
console.log(path)
console.log(search)
return "/" + routeParams.crust
}
})
这样当访问http://localhost:8000/pizza/deep/peppers?delivery=home时候,就都打印出来;而且最后会进入http://localhost:8000/deep这个url
$q deferred & promises
异步和延时处理,当defer.resolve或者defer.reject被处理之后,才会调用当初的promise;resolve则promise成功,reject则拒绝了当初的约定,oh no!
var defer = $q.defer();
defer.promise
.then(function(weapon){
alert("you can have my " + weapon);
return "bow"
})
.then(function(weapon){
alert("And my "+weapon);
return "axe"
})
.then(function(weapon){
alert("And my"+weapon);
})
defer.resolve("sword");
上面是一个简单的例子,下面简单介绍一下两个接口
延迟接口 | Deferred API
通过调用 $q.defer() 可以构建一个新的 deffered 实例。
deffered 对象用来将 Promise 实例与 标记任务状态(执行成功还是不成功)的 API 相关联。
deffered 对象的方法
resolve(value) ——传入 value 解决派生的 promise。 如果 value 是一个通过 $q.reject 构造的拒绝对象(rejection) , 该promise 将被拒绝。
reject(reason) ——拒绝派生的promise,并提供原因 。 这相当于通过 $q.reject构造的拒绝对象(rejection)作为参数传递给 resolve。
notify(value) ——在 promise 执行的过程中提供状态更新。 这在 promise 被解决或拒绝之前可能会被多次调用。
deffered 对象的属性
promise – {Promise} —— 与延迟(deferred)相关联的 promise 对象。
承诺 接口 | Promise API
当创建 deferred 实例时会创建一个新的 promise 对象,并可以通过 deferred.promise 得到该引用。
promise 对象的目的是在 deferred 任务完成时,允许感兴趣的部分取得其执行结果。
promise 对象的方法
then(successCallback, errorCallback, notifyCallback) ——不管 promise 是被处理还是被拒绝, 一旦结果可用,then 就会尽快地异步调用 成功/错误 回调函数 只要结果是可用的。 调用回调函数时传递单个参数: 结果 或拒绝的理由。 此外,notify 回调可能被调用 0到多次,以提供 提供一个进度指示,之前承诺解决或拒绝。
这个方法 返回一个新的promise 对象, 根据 successCallback , errorCallback的返回值进行解决或拒绝 。 它还通过 notifyCallback 方法的返回值进行通知。 promise 不能从notifyCallback方法得到解决或拒绝 。
上面的例子组成了一个promise chain~
介绍完这部分,那么它能够在route这个topic中起到什么作用呢?
route中的defer
var phonecatApp = angular.module('phonecatApp',['ngRoute',]);
phonecatApp.config(function($routeProvider){
$routeProvider
.when("/",{
templateUrl:"hello.html",
controller:"phonecatApp",
resolve:{
loadData: phonecatCtrl.loadData
}
})
});
var phonecatCtrl = phonecatApp.controller('phonecatApp', function($scope){
$scope.model = {
message:"I'm a great app!"
}
})
phonecatCtrl.loadData = function($q, $timeout){
var defer = $q.defer();
$timeout(function(){
defer.resolve();
console.log("loadData");
},2000);
return defer.promise;
}
错误处理
phonecatApp.controller('errorProcess',function($rootScope){
$rootScope.$on("$routeChangeError",function(event,current,previous,rejection){
console.log(rejection);
})
})
然后将此controller绑定到ng-app附近即可
另外一种方法就是使用directive
phonecatApp.directive("error",function($rootScope){
return {
restrict:'E',
template:'<div ng-show="isError">Error!!!!!</div>',
link:function(scope){
$rootScope.$on("$routeChangeError",function(event,current,previous,rejection){
scope.isError=true;
})
}
}
})