架构(MVVM框架)
- Model是简单的javascript对象
- View是Angular解析渲染后生成
- ViewModel是scope对象,Angular依靠scope检测状态变化
- Controller负责设置初始状态和参数化$scope方法用以控制行为,服务于ViewModel
运行机制
备注:模板加载顺序为先内存加载再ajax加载
模块
控制器、服务、过滤器、指令等功能的集合,分为配置阶段和运行阶段
- angular.module(name, [requires], [configFn]);
新建模块
var createModule = angular.module(“myModule”,[]);
//如果重名,会覆盖现有的调用模块
var getModule = angular.module(“myModule”);若不存在,返回空值
引用形式误用为创建形式 对象不存在
创建形式误用为引用形式,返回值为空指针
指令
- 描述:将DOM元素增强为可复用的DOM组件的属性或元素
- 命名:驼峰写法(addBtn),使用时用-分割各单词(add-btn)
参数 :
restrict:
E(元素)A(属性)C(类)M(注释)
template
文本或函数
templateUrl
模板文件名 <script type="text/ng-template" id="demo.html"></script> app.run(function($templateCache) { $templateCache.put('template.html','<div>template</div>'); })
replace
true/fasle
scope
false 继承且不隔离 true,继承且隔离 {}不继承也不隔离 scope: { color: '@' //=(双向绑定),&(调用父作用域) },
transclude
与ng-transclude结合使用
controller
控制器主要用来提供可在指令间复用的行为,可对外提 供与外部交互的接口, 但是link链接只能在当前指令内部中定义行为,且无法在指令间复用。
compile
负责对模板的DOM进行转换,并且仅仅只会运行一次
link
link函数负责将作用域与DOM进行链接 link:function(scope,element,attrs,accordionController){}) //element包装的DOM元素,jQuery元素,attrs获取指令的属性
require
没有前缀 指令会在自身提供的控制器中进行查找,如果找不到任何控制器,则会抛出一个error ? 若在当前指令中没有找到所需的控制器,则会将null传给link链接函数的第四个参数 ^ 如果在当前的指令中没有找到所需的控制器,则会查找父元素的控制器 ?^ 如果在当前和父元素中都没有找到控制器,则会将null传给link
$scope
特点:
执行环境(作用域) 树形结构
方法:
$watch:
//$scope.$watch(newValue,oldValue); var app = angular.module('myApp',[]); app.controller('MainCtrl',function($scope){ $scope.user = {name:"Fox"}; $scope.updated = 0; $scope.$watch('user',function(newValue,oldValue){ if(newValue == oldValue)return ; $scope.update++; },true);//第三个参数表示比较的是对象的值而不是引用 });
$apply:
$scope.$apply()会自动地调用$rootScope.$digest() 如果angular检测不到model的修改,需手动地调用$scope.$apply()
$on:
用于接收event与data
$emit:
只能向parent controller传递event与data
$broadcast:
只能向child controller传递event与data 备注:scope上的只能是数据和行为
过滤器
常用过滤器:
currency :'¥' date:'yyyy-MM-dd hh:mm:ss EEEE' filter:'a'/4/{name:'i'}/func json limitTo:正负数 lowercase uppercase number:2 orderBy:'age' orderFunc ['age','name']
自定义过滤器:
app.filter('map',function(){ var filter = function(){ } }); {{expression | filter:argument1:argument2 | filter2}}
依赖注入使用过滤器:
app.controller('testC',function($scope,currencyFilter)){ $scope.num = currencyFilter(12334); }
控制器
把service、依赖关系以及其它对象串联,通过scope把它们关联到view上 一个控制器一般只负责一小块视图 不要在controller中操作DOM 不要在controller里做数据格式化 不要在controller里做数据过滤操作 controller之间不会相互调用
服务
可以让controller和directive访问内部的数值
路由
加载机制
服务$routeProvider定义路由表:地址栏与视图模板的映射 $routeParams保存地址栏中的参数 $route完成路由匹配及相关属性及访问事件 指令ngView用来在主视图中指定加载子视图的区域
配置:
var app = angular.module('myApp',['ngRoute']); when(path,route) path: /show/:name /show*/:name route: controller controllerAs template: templateUrl: resolve redirectTo otherwise(params) $location: path() replace() search() url()
指令
ng-view: 优先级:终极1000 创建新的作用域 $viewContentLoaded事件 $routeChangeSuccess reloadOnSearch
路由模式
标签模式 HTML5模式
路由事件
$routeStartChange $routeChangeSuccess $routeChangeErrorr $routeUpdate $urlRouterProvider路由重定向 app.config(['$stateProvider','$urlRouterProvider',function($stateProvider,$urlRouterProvider){ $urlRouterProvider.when('/user/:id') }]) $urlRouterProvider.rule(function($injector,$location){}) $stateProvider状态配置 $stateProvider.state('contacts',{ url:“/contacts/:contactId”, //contacts/{contactId} /contacts?myParam&myParam2 templateUrl:"contacts.detail.html" }) 附加模式 .state('contacts.list',{ url:'/list' // ‘^/list'附加失效 urlMatcher resolve:function($state){ return $state.current.params.contactId }, }) $stateParams服务 $state.current.params
依赖和服务注入
//controller注入服务: someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1,dep2) { ... $scope.aMethod = function() { ... } ... }]); //配置注入服务: angular.module('myModule', []). config(['depProvider', function(depProvider){ ... }]). //factory注入服务: factory('serviceId', ['depService', function(depService) { ... }]). //指令注入服务: directive('directiveName', ['depService', function(depService) { ... }]). //过滤器注入服务: filter('filterName', ['depService', function(depService) { ... }]). run(['depService', function(depService) { ... }]);
表单相关
$valid ng-valid $invalid ng-invalid $pristine ng-pristine $dirty ng-dirty ng-submit ng-minlength ng-maxlength ng-pattern ng-show="loginFrom.username.$error.required" ng-show="loginFrom.username.$dirty&&loginFrom.username.$invalid" ng-disabled="loginForm.$invalid“ angular.copy(source,destination) angular.equals(user,$scope.saved); 通过 $scope.yourForm.inputText.$error.required 来判断输入框是否为空 通过 $scope.yourForm.inputText.$invalid 来判断输入的内容是否满足ng-pattern,ng-maxlength,maxlength
附加模块
ngResourceß
angular动画
//todo
常用功能
排序
<li ng-repeat="person in persons | orderBy:'name'">
异步请求
参数:
method方法: url路径 params GET请求参数 headers头 transformRequest 请求预处理函数 transformResponse响应预处理函数 cache缓存 timeout超时毫秒 withCredentials跨域 $http.get({url:"/xxx.action"}).success(function(data){ alert(data); }).error(function(){ alert('error'); }); $http.delete(url,config) $http.get(url,config) $http.head(url,config) $http.jsonp(url,config) $http.post(url,data,config) $http.put(url,data,config) defaults请求的全局配置 pendingRequests当前的请求队列状态 $http({ method:'', url:'', headers:{ ClientType:'Web', Equiment:'', }, data:data }).success(fn).error(fn) 返回promise对象 promise.then(function(resp){}, function(resp){ }) 或者: promise.success(function(data,status,config,headers){ //处理成功的响应 }); promise.error(function(data,status,hedaers,config){ //处理失败后的响应 }); $http.get('',{cache:true})
设置请求头:
1、通用配置 angular.module('app', []) .config(function($httpProvider) { $httpProvider.defaults.headers.common = { 'My-Header' : 'value' } }) 2、个性化配置 $http.post('/somePath' , someData , { headers : {'Authorization' : authToken} }).success(function(data, status, headers, config) { //... }).error(function(data, status, headers, config ) { //... }); 3、处理验权、授权方面 myModule.factory('authInterceptor', function($rootScope, $cookies){ return { request: function(config){ config.headers = config.headers || {}; if($cookies.get('token')){ config.headers.authorization = 'Bearer ' + $cookies.get('token'); } return config; }, responseError: function(response){ // ... } }; }) .config(function($httpProvider){ $httpProvider.interceptors.push('authInterceptor'); })
设置样式
ng-class="{true:'active',false:'inactive'}[isActive]" ng-class="{'selected':isSelected,'car':isCar}"
设置angular全局变量
1、通过var 直接定义global variable,这根纯js是一样的。 2、angularjs.value() 3、app.constant()
config的参数
$locationProvider: html5模式 hashPrefix前缀 $locationProvider.html5Mode(true).hashPrefix('!');
viewName@stateName
.state('index.CarPage', { url: '/CarPage', views: { 'main@index': { templateUrl: 'assets/views/CarPage.html', controller:'carPageController', } } })
$q
$q内置服务,异步的执行函数 $q.defer()延迟 延迟对象 deferred.promise返回当前任务完成的结果 deferred.resolve(value)成功解决 deferred.reject(reason) $q.all()用于执行多个异步任务回调
ngModel
ngModel.$viewValue 视图的实际值 ngModel.$modelValue ng-model的值 ngModel.$setViewValue('') ngModel.$parsers验证和转化 ngModel.$formatter格式化和转化 ngModel.$viewChangeListeners ngModel.$setPristine() ngmodel.$setValidity ngModel.$render() ngModel.$error ngModel.$name ngmodel.$setValidity('flag',布尔值)
angular表达式与javascript表达式的区别
都可以包含字母、操作符、变量 不同之处: javascript的执行环境在全局作用域中 ng是在一个scope对象中 不能在ng表达式({{}})中使用条件判断循环或异常 不能在ng表达式中声明方法 不能创建正则表达式的实例 不能使用new操作符创建对象 如果要运行一些比较复杂的JavaScript表达式,应该封装成$scope的一个属性在控制器当中,并在视图中调用。
15.常用指令
ng-bind与{{}}的区别:ng-bind数据加载完再显示
ng-app
ng-init
ng-model
ng-bind
ng-repeat $index,$first,$middle,$last、$odd、$even
ng-class
ng-class-odd,ng-class-even
ng-style
ng-show
ng-if
ng-hide
ng-switch
<div ng-init="a=2">
<ul ng-switch on="a">
<li ng-switch-when="1">1</li>
<li ng-switch-when="2">2</li>
<li ng-switch-default>other</li>
</ul>
</div>
事件指令
ng-change
ng-click
ng-dbclick
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-submit
$event
$event.target
表单指令
form
ng-form
<form name="test_form" ng-controller="TestCtrl">
<input type="text" name="a" required ng-model="a"/>
<span ng-click="see()"></span>
</form>
var TestCtrl = function($scope){
$scope.see = function(){
console.log($scope.test_form);
console.log($scope.test_form.a);
}
}
$pristine 表单或者输入框没有使用则为true
$dirty 表单或者输入框有使用到则为true
$valid 设定的规则是否验证通过
$invalid 设定的规则是否验证未通过
$error验证的错误信息
<form name="test_form" ng-controller="TestCtrl">
<input type="text" name="a" ng-model="a" required ng-pattern="/abc/">
<span ng-click="see()"></span>
</form>
input可用属性
name
ng-model
required
ng-required
ng-minlength
ng-maxlength
ng-pattern
ng-change
ng-trim
checkbox
<input type="checkbox" name="a" ng-model="a" ng-true-value="AA" ng-false-value="BB">
radio
<input type="radio" name="a" ng-model="a" value="AA">
<input type="radio" name="a" ng-model="a" value="BB">
select:
<select ng-model="selectedCar" ng-options="y.brand for (x, y) in cars"></select>
<select ng-model="a" ng-options="v.v as v.name for (k,v) in o"></select>
//ng-option 对象
//ng-repeat 字符
ng-src
ng-href
ng-checked
ng-selected
ng-disabled
ng-multiple
ng-readonly
16、angular注意点
- AngularJS 中的友好 URL —— 移除URL 中的 #
angular.module('router', ['ngRoute']) .config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
}
- ng-click直接传表达式,无需加{{}}
<a ng-click="obja=1;objb=2"></a>
在能使用ng-if的情况,用它代替所有的ng-show和ng-hide
获取ng-repeat数据filter后的结果(搜索的情况用得比较多)
//简洁快捷方式
ng-repeat="food in foodCategory._displayfoods = (foodCategory.foods | filter: { 'name': searchobj.foodfilter } | orderBy: food.sort_order)"
//性能优良方式
另一种方式是通过两套数据,一套写在controller中,然后filter以及orderBy都是在controller中操作,最后操作的结果在用来ng-repeat.
- ng-class以及ng-style通过判断赋值
ng-class="{'state-error':!foodForm.foodstock.$valid}"
ng-style="{ color: i.color=='' || i.name=='活' ? 'default' : '#fff' }"
- $resource用法示例
var User = $resource('/user/:userId', {userId:'@id'}); // 返回一个资源对象
/* 操作资源 */
User.get({userId:123}, function(user) {
// do something
});
/* 如果想用Promise风格 */
User.get({userId:123}).$promise.then(function(user) {
$scope.user = user;
});
- 仅$watch监听collection中的一个属性
$scope.people = [
{
"groupname": "g1",
"persions": [
{
"id": 1,
"name": "bill"
},
{
"id": 2,
"name": "bill2"
}
]
},
{
"groupname": "g2",
"persions": [
{
"id": 3,
"name": "bill3"
},
{
"id": 4,
"name": "bill4"
}
]
}
]
$scope.$watch(function($scope) {
return $scope.people.map(function(obj) {
return obj.persions.map(function(g){
return g.name
});
});
}, function (newVal) {
$scope.count++;
$scope.msg = 'person name was changed'+ $scope.count;
}, true);
- resolve
可以使用resolve为控制器提供可选的依赖注入项。
key – {string}:注入控制器的依赖项名称。
factory - {string|function}:
string:一个服务的别名
function:函数的返回值将作为依赖注入项,如果函数是一个耗时的操作,那么控制器必须等待该函数执行完成(be resolved)才会被实例化。
usr-sref-active
查看当前激活状态并设置 Class
ionic