AngularJS 使用
一、AngularJs 路由的使用
1. 路由的作用
从技术上来说AJAX应用确实是单页面应用(即在第一个请求时加载一个HTML页面,后面只刷新DOM中的局部区域),但是很多时候,出于各种原因,我们需要为用户展示或隐藏一些子页面视图。针对这一方面,我们可以利用Angular 的 $route 服务来管理这种场景。可以利用路由服务来定义这样一种东西:对于浏览器所指定的特定URL,Angular 将会加载并显示一个模板,并实例化一个控制器来为模板提供内容。
2. 路由的配置
- 环境
angular.min.js
angular-resource.min.js
angular-route.min.js
- 创建App Module
var app = angular.module("appName",["需要引入的模块"]);
- 配置路由
app.config(["$routeProvider", "$provide", function($routeProvider, $provide){
$routeProvider
.when('/', redirectTo: '/index')
.when('/:page', {
templateUrl: function($routeParams){
return "module/" + $routeParams.page + '/index.html';
}
})
.when('/特定url', redirectTo: '/特定页面')
.otherwise({
redirectTo: '/index'
});
}]);
- 指定主模块的配置,需要在主模块中引入模块
'ngRoute'
- 在config函数中可以按需引入,如这里必须引入
$routeProvider
,这里也可以写成
app.config(function($routeProvider, $provide){//内容主体})
- $routeProvider 下每个when都代表一个特定的地址,Angular将会根据浏览器中的URL自动去找相对应的when并执行when里面响应的内容
- when 中可以有不同写法
when('/特定URL', redirectTo: '特定页面地址')
,这种为根据特定的URL跳转到特定的页面when('/特定URL', {controller:'该模板页面对应的controller', templateUrl: '模板地址'})
,如果指定了controller,首先需要在主模块中引入该controller,如我有一个controller:angular.module('testController',[]).controller('controllerName',function(){})
,则在主模块[]
中引入即可['testController']
(请务必先将controller所在js文件加载)when('/:page', {templateUrl: function($routeParams){return "module/" + $routeParams.page + '/index.html';}})
如果整个项目的页面有一定的规则,如在这里页面都位于module
文件夹下,并且都是位于page指定的子文件夹的index,html页面,则可以直接在URL上使用占位符/:page
,再通过$routeParams获得URL中:page
所指定的值,拼装后即是完整的路劲。如,我需要跳转至module/test/index,html
页面,则我只要将地址写为/test
即可。otherwise({redirecTo:'/index'})
,告诉路由在没有匹配到任何东西时跳转到该配置指定下的路劲redirectTo
,跳转至指定路劲
3. 使用路由
- 在controller中引入
$location
,需要跳转页面时直接使用$location.path('/地址')
。如
angular.module('testController',[]).controller('controllerName',function($scope, $location){
function test(){
$location.path('/地址');
}
})
二、自定义指令
1. 指令的理解
AngularJs 除了自带的固有指令外,还可以自定义指令来实现一些特殊的需求。
2. 指令的伪代码模板
var myModule = angular.module(...);
myModule.directive('namespaceDirectiveName', function(injectables){
var directiveDefinitionObject = {
restrict: string,
priority: number,
template: string,
templateUrl: string,
replace: bool,
transclude: bool,
scope: bool or object,
controller: function controllerConstructor($scope, $element, $attrs, $transclude),
require: string,
link: function postLink(scope, iElement, iAttrs){...},
complie: function compile(tElement, tAttrs, transclude){
return {
pre: function preLink(scope, iElement, iAttrs, controller){...},
post: function postLink(scope, iElement, iAttrs, controller){...}
}
}
}
return directiveDefinitionObject;
});
- restrict 描述了指令在模板中的使用方式,包括:元素(E)、属性(A)、CSS样式类(C)、注释(M)或者以上几种方式的任意组合
- priority 设置指令在模板中的执行顺序,顺序是相对于元素上的其他指令而言
- template 以字符串的形式编写一个内联模板,如果以URL的方式提供模板,此属性会被忽略
- templateUrl 描述加载模板所要使用的URL,如果使用字符串的形式提供内联的模板,此属性会被忽略
- replace 如果此配置项为true,则替换指令所在的元素。如果为flase或者不指定,则把当前指令追加到所在的元素内部
- transclude 把指令元素中原来的子节点移动到一个新模板内部
- scope 为当前指令创建一个新的作用域,而不是使之继承父作用域
- controller 创建一个控制器,它会暴露一个API,利用这个API可以在多个指令之间进行通信
- required 要求必须存在另一个指令,当前指令才能正确执行
- link 使用编程的方式修改最终生成的DOM元素实例,添加事件监听器,并设置数据绑定
- compile 在使用ng-repeat时,用编程的方式修改DOM模板,从而实现同一个指令的跨越多个实例的特性。complie 函数也可以返回一个link函数,可以用它来修改产生的元素实例。
3. 指令的使用
angular.module('processbar.directive', []).directive('processbar', function () {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: {paramOne: '@paramOne', paramTwo: ':=paramTwo', paramThree: '¶mThree'},
template: "<div></div>",
link: function (scope, element, attrs) {
}
};
});
scope
类型
- 现用的scope scope: false(如果不指定,是默认值)
- 新scope scope: true
- 独立scope scope: {/属性名和绑定分隔/}
绑定策略
- @ 把当前属性座位字符串床底。你还可以绑定来自外层scope的值,在属性值中插入{{}}即可
- = 绑定当前属性,它带有一个来自指令父scope的属性
- & 传递一个来自父scope的函数,稍后调用
使用注意
- 在使用参数时,应该避免与其它已知参数冲突,如命名为 ngRepeat 等,此种命令方式会产生冲突导致无法正常使用
- 在使用参数时,如果参数命令符合驼峰命名规则如
paramOne
,则在调用该组件时该参数应该写为param-one
- 如果scope: false或者不写,则默认会继承父Controller的scope域,可以对里面的内容进行一些操作,从而影响父容器
template
- 该属性里可以直接写模板,如
<div></div>
- 在模板中如果需要调用scope中的属性,与正常页面使用AngularJS一样,如
{{xxx}}
等
link:scope 参数
- 如果没有设置scope属性或者scope: false,则该scope继承了父容器的内容,对该scope域中的影响将同步影响到父容器中。
- 如果设置了scope属性为独立scope,则该scope域所包含的为所设置的属性名,如
{paramOne: '@paramOne'}
,则如果paramOne有值,则可以通过scope.paramOne
直接访问 - 可以通过使用
=
绑定操作符,绑定父容器scope域中的某个值,在指令中通过watch
函数来监听其值的变化,继而做出不同的处理。使用=
绑定符时,不要求参数名称与主容器scope域中的参数名称相同
link:element 参数
- 该参数的值为template或templateUrl的内容
- element[0] 代表获得DOM元素,可以对其进去DOM操作
link:attrs 参数
- 写在指令上的属性,可以通过这个参数获得
指令使用总结
- 如果指令中需要根据父容器中的某些值得变化而做一些处理,可以采用在
scope
参数中使用=
引入父容器的属性,进而使用watch
函数对比进行监听,如:
scope: {currentPage: "=currentPage"}
scope.$watch('currentPage', function (newValue, oldValue) {
console.info("监听到了" + newValue);
});
三、拦截响应
1. 拦截响应格式
myModule.factory('myInterceptor', function($q, notifyService, errorLog){
return function(promise){
return promise.then(function(response){
//响应正常,不用处理
return response;
}, function(response){
//进行错误处理
//最后返回
return $q.reject(response);
})
}
});
2. 响应错误处理范例
根据响应码进行处理
if (response.status === 401) {
$rootScope.$broadcast('errorResponse', response.data);
$window.location.href = ".";
} else if (response.status === 403) {
$rootScope.$broadcast('errorResponse', response.data);
alertException(response.data);
} else if (response.status === 404) {
$rootScope.$broadcast('errorResponse', response.data);
alert("未找到对应链接,或访问服务器失败");
} else if (response.status === 405) {
$rootScope.$broadcast('errorResponse', response.data);
} else if (response.status === 415) {
$rootScope.$broadcast('errorResponse', response.data);
} else if (response.status === 500) {
$rootScope.$broadcast('errorResponse', response.data);
}
四、其它
- 在$resource中使用占位符,若在使用时未指定值则不显示,如‘/TestMaven/api/ds/:dsId/:form/:to’
若我的参数列表为{dsId:’1’},则url实际为‘/TestMaven/api/ds/1’。之后的两个参数并不显示。 - 使用{id:’@id’},如果传递的是一个对象并且包含id属性,则会自动复制,在做对象的保存时,因为为新建
对象,所以不具有id属性。 - 一个模块可以具有多个Controller,名字不能相同
- 在使用ng-include 时,如果该指令所在标签嵌套在其它模块中,则必须在父模块中引用该模块
main.html
<body ng-app="testApp" >
<!-- 头部 -->
<div>
1213132
</div>
<!-- 导航栏 -->
<!--注意这里的''-->
<div ng-include="'module/navPage.html'"> </div>
<script src="/TestMaven/js/customJS/test.js"></script>
<script src="/TestMaven/js/customJS/navCtr.js"></script>
</body>
navPage.html
<!--这里ng-app="navApp" 可有可无-->
<div ng-controller='navController'>
<table>
<tr>
<td>业务类型</td>
<td>全部</td>
<td>网页浏览</td>
</tr>
<tr>
<td>指标</td>
<td>指标1</td>
<td>指标2</td>
</tr>
</table>
</div>
test.js
angular.module('testApp',['navApp']).controller('testController',function($scope){
});
navCtr.js
angular.module('navApp',[]).controller('navController',function($scope){
console.info("测试");
});