为何需要MVC
- 代码规模越来越大,切分是大势所趋
- 为了复用:逻辑,用法一样的模块
- 后期维护方便:修改一块功能不影响其它功能
- MVC只是手段,终极目标是模块化和复用
- 一切从模块开始
- 模块之间依赖注入
- 双向数据绑定
要点
Controller使用过程中的注意点
不复用----------------(一个控制器一般只负责一小块视图)
不操作DOM-------------(非其职责)/用Angularjs中directive操作DOM
不做数据格式化--------(ng有好用的表单控件)
不做数据过滤----------(ng有$filter服务)
不相互调用------------(一般不相互调用,控制器间的交互会通过事件进行)
Model复用
- 视图复用:通过directive实现
- *AngularJS的MVC是借助于$scope实现的
- AngularJS的数据结构跟HTML的标签层级一样是树形的
- $emit('')向上传播
- $broadcast('')向下/同层传播
神奇的$scope
- 是一个pojo--(普通的JAVASCRIPT对象)
- 其工具方法---$watch/$apply
- 是执行环境---是表达式的执行环境(作用域)
- 树型结构-----与DOM标签平行
- 继承----------(子$scope对象会继承父$scope上的属性和方法)
- 只有一个根$scope对象--每个ng应用只有一个根$scope对象(一般位于ng-app)
- 可传播事件--类似DOM事件(可向上和向下)
- 是基础--(MVC和双向数据绑定)
- 调试--angular.element($0).scope();
AngularJS模块化实现
angular.module('app名',[])定义模块
基础笔记
-
$scope.$apply:
-
$apply
会手动触发脏检查,如果$apply
不传参数,会自动脏检查所有参数
例--1秒检查改变一次$scope.date
-
setInterval(function(){
$scope.$apply(function(){$scope.data=new date;})
},1000)
-
其中机制:
$apply
首先会将传进的表达式给$eval
解析 错误的话会传给$exciptionHandler
报错 正确的话会传给$digest()
执行- 真正触发脏检查的是
$digest()
- 所以直接调用
$digest
不够保险 应由$eval
把关
- 真正触发脏检查的是
-
$watch监听
- 函数语法:
$watch(要监听值,function(newValue/改变后的值,oldValue/改变前的值){})
- 当监听对象或监听对象中多个值时:
$watch(要监听的对象/json、array等,function(newValue/,oldValue/){},true)
其中第三个值true表示对象中有一个值改变就触发
-
数据共享
- $provide.provider+this.$get(){return }
之后在controller中注入
简便方法:factory,service
factory可返回任何数据类型,而 service只能返回对象类型
- $provide.provider+this.$get(){return }
- 通过作用域链取到相邻的controller相邻的
$scope($scope.$$prevSibling/$scope.$$nextSibling)
-
过滤器
- 在控制器中用过滤器 在参数中注入
$filter(controller('mycontroller',function($scope,$filter){}))
- 用法
- 在控制器中用过滤器 在参数中注入
var number = $filter('number')(3000)
//声明number变量赋值3000并用number过滤
- 自定义方法
在'|'后定义一个函数(在控制器中) 例:
$scope.checkName=function(obj){
if(obj.content.indexOf('h')===-1)return false;
return true}
//匹配带有'h'的结果
-
controller的正确写法:
- 将依赖注入由隐示写为显示
(为了防止压缩代码时使$scope
等参数无效)
.controller('mycontroller',function($scope,$filter){})
-->
.controller('mycontroller',['$scope','$filter',function(a,b){}])
//a就是$scope,b是$filter
-
angular中的注入属性$inject:
function controller(a){a就是$scope};controller.$inject=['$scope']
-
内置渲染指令
ng-include="'other.html'" / ng-include src="'other.html'" 在标签中引入另一个页面
事件
在标签中引用事件对象
例:<button ng-click="change($event)">{{status}}</button>
$scope.status=true;
$scope.change=function(event){
//将其转化为JQuery对象
$scope.status=!$scope.status;
$scope.element(event.target).html($scope.status)
}
自定义指令
同一个元素上只能有一个template渲染 有多个时执行第二个会报错
设定指令优先级:priority:1 /越大优先级越高
AngularJS指令编译的三个阶段
1.标准浏览器API转化
将HTML转化为DOM
2.Angular compile
搜索匹配的directive,按照priority排序,并执行directive上的compile方法
3.Angular link
执行directive上的link方法,进行scope绑定与事件绑定compile中返回的值就是link 并会自动运行 之后的link不需要再定义 编译阶段: compile:function(tElement,tAttrs,transclude){ tElement:当前元素的JQeury对象 tAttrs:当前元素的属性 transclude:被替换对象的原始数据 /没有就是undefined return{ //表示在编译阶段之前,指令连接到子元素之后运行 pre:function preLink(scope,iElement,iAttrs,controller){ scope:当前元素的作用域 iElement:当前元素的JQuery对象 }, //表示在所有子元素指令都连接之后才运行 post:function postLink(scope,iElement,iAttrs,controller){ } }//返回的link函数 }, link:function(scope,iElement,iAttrs,controller){ //同compile中的postLink 若compile中以有 此处不要再定义 } compile和link的使用时机 compile: 想在DOM渲染前对它进行变形,并且不需要scope参数 想在所有相同的directive里共享某些方法, link: 对特定的元素注册事件 需要用scope参数来实现DOM元素的一些行为 指令中的controller: 与之前的controller功能相同 会暴露一个API 供require调用 在多个指令之间互相通讯 require: 调用别的指令:directiveName 请求的指令名 默认从同级元素上找 ^directiveName 请求父级的指令 ?directiveName 指令可选 没有也不会报错 scope: 为当前指令创建一个新的作用域,而不是继承父作用域 false:完全与外面的controller相同 true:创建一个新的作用域 但会继承父作用域 {}:独立的作用域 其中:& 将父作用域的属性封装成一个函数,将其内容写进该作用域内 = 将该作用域与父作用域进行双向绑定,一个改变另一个也会跟着改变 @ 将该作用域与父作用域单向绑定 *注意标签属性要对应
constant,value
用于在整个应用开始前定义一个全局的常量 之后在controller里通过注入调用
属于$provider里的方法 简便方法:直接用.constant('名字','内容')
constant可注入任何方法 value只可注入controller service factory
run
在config之后 其他服务之前运行
表单
$setPristine方法 将表单重置(只重置其中的class $dirty $pristine)
字段是否未更改
formName.inputName.$pristine
字段是否更改
formName.inputName.$dirty
字段有效
formName.inputName.$valid //=true
字段无效
formName.inputName.$invalid //=true
字段错误信息
formName.inputName.$error
input 属性
name/名字 ng-model/绑定数据 ng-required/是否必填 ng-minlength,ng-maxlength/最小最大长度 ng-pattern/自定义匹配模式 ng-change/值变化时回调
ng-model属性
ng-model是angular原生的directive指令 名为ngModel 可以在directive里require:'ngModel'引用他
其带有的属性
$parser 保存了从viewValue向modelValue绑定过程中的处理函数,他们将来会依次执行
$formatters 保存的是modelValue向viewValue绑定过程中的处理函数
$setViewValue 当view发生某件事,从view向model绑定调用$setViewValue 把viewValue保存下来
$render 当模型发生变化时,应该怎么去更新视图,从model向view绑定 调用ctrl.$render方法 将viewValue渲染到页面上
$setValidity 设置验证结果
$viewValue 视图的值
%modelValue 模型里的值