AngularJS 是什么
- 概念:
- AngularJS主要用于构建单页面Web应用,是一种构建动态Web应用的结构化框架。
- 核心功能:
- 模块化、双向数据绑定、语义化标签、依赖注入(行内注入、推断式注入)、$http等。
AngularJS模块(使用angular.module()方法来声明模块)
- 优点:
- 保持全局命名空间的清洁;
- 编写测试代码更容易,并能保持其清洁,以便更容易找到互相隔离的功能;
- 易于在不同应用间复用代码;
- 使应用能够以任意顺序加载代码的各个部分。
实现模型-视图的双向绑定
- 数据绑定就是数据与视图的一一对应关系,模板引擎为单向绑定,AngularJS为双向绑定
- 通过model建立数据模型,视图上的数据就会对应存储在angular程序里,视图上的数据变化会同步到model,model的数据改变也会同步到视图
- 脏检查机制(dirty-checking)是实现双向数据绑定的重要基础。
- 脏检查机制:Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ng-bind,ng-show等或是{{}})。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。
- 脏检查机制的触发:Angular中在view上声明的事件指令,如:ng-click、ng-change等,会将浏览器的事件转发给digest循环。当循环结束后,才把模型的变化结果更新到dom中去,防止频繁的dom操作。
<input type="text" ng-model="msg">
<!-- 视图——>模型 -->
<h1 ng-bind="msg"></h1>
<!-- 模型——>视图 -->
<h1>{{msg}}</h1>
<!-- 模型——>视图 -->
引入第三方路由模块 ngRoute 配置路由实现单页面开发
- SPA(Single Page Application)指的是通过单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互。
//配置路由
var Yike = angular.module('Yike',['ngRoute','Controllers']);
Yike.config(['$routeProvider',function($routeProvider){
$routeProvider.when('/today',{
//今日一刻
templateUrl:'./views/today.html',
controller:'TodayCtrl'
}).when('/settings',{
//设置
templateUrl:'./views/settings.html',
controller:'SettingsCtrl'
}).otherwise({
redirectTo:'/today'
});
}]);
理解MVC、MVVM开发模式
- MVC(Model View Controller,模型(数据保存)视图控制器):一种软件架构设计模式,它将表现从用户交互中分离出来。通常来讲,模型中包含应用的数据和与数据进行交互的方法,视图将数据呈献给用户,而控制器则是二者之间的桥梁。
- View 传送指令到 Controller
- Controller 完成业务逻辑后,要求 Model 改变状态
- Model 将新的数据发送到 View,用户得到反馈
- MVP(Model-View-Presenter):把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当桥梁,做到View-Model之间通信的完全隔离。各部分之间的通信,都是双向的。
- MVVM(Model-View-ViewModel):将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。唯一的区别是,它采用双向绑定(data-binding):View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到View上。如js框架Knockout、AngularJS等。
使用directive自定义指令、验证表单字段
app.directive('tag',function(){
return {
//指令调用方式:E:element,C:class,M:mark,A:attribute
restrict:"ECMA",
//为true时M显示,不写或为false不显示。是否替换原始标签
replace:true,
//指令内容
template:'<h1>你好 angular</h1>',
//加载外部文件,需通过服务器访问
//templateUrl:'./header.html'
}
});
<form name="myForm">
<div class="form-group">
<label for="">User name:</label>
<input type="text" class="form-control" name="userName" ensure-unique="username" ng-model="user.name" required>
<span class="error" ng-show="myForm.userName.$error.unique">Required!</span>
</div>
<div class="form-group">
<label for="">Last name:</label>
<input type="text" class="form-control" name="lastName" ng-model="user.last" ng-minlength="3" ng-maxlength="10">
<span class="error" ng-show="myForm.lastName.$error.minlength">Too short!</span>
<span class="error" ng-show="myForm.lastName.$error.maxlength">Too long!</span>
</div>
<div class="form-group">
<label for="">User age:</label>
<input type="text" class="form-control" name="userAge" ng-model="user.age" even required>
<span class="error" ng-show="myForm.userAge.$error.even">数字必须是偶数</span>
</div>
</form>
angular.module('MyApp', [])
.controller('ExampleController', ['$scope', function ($scope) {}])
.directive('even',function(){
return {
restrict:"A",
require:"ngModel",
link:function(scope,ele,attrs,ngModelController){
//$parsers的值是一个由函数组成的数组,其中的函数会以流水线的形式被逐一调用。ngModel从DOM中读取的值会被传入$parsers中的函数,并依次被其中的解析器处理。
ngModelController.$parsers.push(function(viewValue){
if(viewValue % 2 === 0){
//通过$setValidity()函数设置表单的合法性
ngModelController.$setValidity('even',true);
}else{
ngModelController.$setValidity('even',false);
}
return viewValue;
});
}
}
})
.directive('ensureUnique', ['$http','$timeout','$window',function($http,$timeout,$window) {
return {
restrict:"A",
require: 'ngModel',
link: function(scope, ele, attrs, ngModelController) {
scope.$watch(attrs.ngModel, function(n) {
if (!n) return;
$timeout.cancel($window.timer);
$window.timer = $timeout(function(){
$http({
method: 'get',
url: '/api/checkusername/', //根据换成自己的url
params:{
"username":n
}
}).success(function(data) {
//这个取决于你返回的,其实就是返回一个是否正确的字段,具体的这块可以自己修改根据自己的项目
ngModelController.$setValidity('unique', data.isUnique);
}).error(function(data) {
ngModelController.$setValidity('unique', false);
});
},500);
});
}
};
}]);
自定义指令参数
- restrict:EACM,默认A
- terminal:true或false,告诉AngularJS停止运行当前元素上比本指令优先级低的指令。但同当前指令优先级相同的指令还是会被执行
- template:一段HTML文本或一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个代表模板的字符串
- templateUrl
- replace:true或不写。默认值意味着模板会被当作子元素插入到调用此指令的元素内部
- scope:
- false:直接调用相同的作用域对象
- true:从当前作用域对象继承一个新的作用域对象
- {}:创建一个同当前作用域相隔离的作用域对象
广播
使用$httpProvider对请求进行拦截实现权限管理
-
httpProvider.interceptors数组中添加服务工厂,在$httpProvider中进行注册。
//创建拦截器,可以在服务中添加一种或多种拦截器
angular.module('myApp', []).factory('myInterceptor', function($q) {
var interceptor = {
//请求拦截器进行调用。它可以对设置对象进行修改
'request': function(config) {
// 成功的请求方法
return config; // 或者 $q.when(config);
},
//对响应拦截器进行调用。它可以对响应进行修改
'response': function(response) {
// 响应成功
return response; // 或者 $q.when(config);
},
//在上一个请求拦截器抛出错误时调用此拦截器
'requestError': function(rejection) {
// 请求发生了错误,如果能从错误中恢复,可以返回一个新的请求或promise
return rejection; // 或新的promise
// 或者,可以通过返回一个rejection来阻止下一步
// return $q.reject(rejection);
},
//在上一个响应拦截器抛出错误时调用此拦截器
'responseError': function(rejection) {
// 请求发生了错误,如果能从错误中恢复,可以返回一个新的响应或promise
return rejection; // 或新的promise
// 或者,可以通过返回一个rejection来阻止下一步
// return $q.reject(rejection);
}
};
return interceptor;
});
//将实现的拦截器加入到$httpProvider.interceptors数组中,一般在config方法中进行
myApp.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push(myInterceptor);
}]);
使用angular-translate实现国际化
- i18n(Internationalization):国际化,在不改变源码的情况下,通过某些简单的配置就能适应不同的语言环境。
- l10n(Localization):本地化,针对某一些语言进行定制化。
- angular-translate是一款应用简单、上手容易的国际化服务。它提供了很多的特性:
- 以组件化的方式形成国际化
- 异步加载国际化数据
- 使用messageFormat支持多元化
- 使用接口提高可扩展性
- translate中指令是通过过滤器实现的,过滤器是通过服务实现的。
- 如果使用了requireJS这种异步加载服务,那么需要声明angular-translate与angular的依赖关系
- 本地化
shim: {
angular_translate:{
deps: ['angular'],
exports: 'angular_translate'
}
}
<div>
<h1>{{ 'TITLE' | translate }}</h1> //以过滤器的方式使用
<span translate="FOO"></span> //指令的方式使用
</div>
var app = angular.module("MyApp",['pascalprecht.translate']);
app.config(['$translateProvider',function($translateProvider){
//添加翻译表格
$translateProvider.translations('en',{
'TITLE':'Hello',
'FOO':'This is a paragraph'
});
$translateProvider.translations('zh',{
'TITLE':'你好',
'FOO':'这是一幅图'
});
//设置首选语言
$translateProvider.preferredLanguage('zh');
}]);
app.controller('TranslateController', ['$translate','$scope',function($translate, $scope) {
$scope.changeLanguage = function(langKey) {
$translate.use(langKey);
}
}]);
<div ng-controller="TranslateController">
<button ng-click="changeLanguage('de')" translate="TITLE"></button>
<button ng-click="changeLanguage('en')" translate="FOO"></button>
</div>
网友评论