AngularJS 学习笔记(2)
2017-09-05 16:28
447 查看
观看angularJS视频教程做了如下笔记:
angular是怎么知道变量发生了改变:
要知道一个变量变了,方法不外乎两种:
1.能通过固定的接口才能改变变量的值,比如说只能通过set()设置变量值,set被调用时比较一下就知道了。
2.脏检查,将元对象复制一份快照,在某个时间,比较现在对象与快照的值,如果不一样就表明发生变化,这个策略要保留两份变量,而且要遍历对象,比较每个属性,这样会有一定性能问题。
angular的策略
angular的实现是使用脏检查。
1.不会脏检查所有对象,当对象被绑定到html中,这个对象添加为检查对象(watcher)。
2.不会脏检查所有属性,同样当属性呗绑定后,这个属性被列为检查的属性。
在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了n个属性,就会添加n个watcher。
什么时候去脏检查
angular所系统的方法中都会触发比较事件,比如:controller初始化的时候,所有已ng-开头的事件执行后,都会触发脏检查。
如何手动触发脏检查
所属的
不建议直接调用
在angular.js框架文件中如何编写
例子:
2.
在
AngularJS内部的watch实现了页面随吗,model的及时更新。
$watch(watchFn,watchAction,deepWatch)
watchFn:angular表达式或函数的字符串。
watchAction(newValue,oldValue,scope):watchFn发生辩护会被调用。
deepWatch:可选的布尔值命令,检查被监控的对象的每个属性是否发生变化。
例子:
angular有自己的生命周期。循环给一个 angular监听的变量复值时。最好还是用angular自带的循环方法。
参数如下:
objs:需要遍历的集合
data:遍历时当前的数据
index:遍历时当前索引
array:需要遍历的集合,每次遍历时都会把objs原样的传一次。
也可以不用写后面两个参数:
例子:
运行结果为:
什么是Module?
大部分应用都有一个主方法(main)用来实例化、组织、启动应用。
AngularJS应用没有主方法,而是使用模块来声明应用应该如何启动。
模块允许通过声明的方法来描述应用中的依赖关系,以及如何进行组装和启动。
Angular模块
模块是组织业务的一个框框,在一个模块当中定义多个服务。当引入了一个模块的时候,就可以使用这个模块提供的一种或多种服务了。
AngularJS本身的一个默认模块叫做ng,它提供了
服务只是模块提供的多种机制中的一种,其他的还有指令(directive),过滤器(filter),及其他配置信息。
也可以在已有的模块中新定义一个服务,也可以先定义一个模块,然后在新模块中定义新服务。
服务是需要显示地声明依赖(引入)关系的,让ng自动地做注入。
Module优点
启动过程是声明式的,更容易懂。
在单元测试是不需要加载全部模块的,因此这种方式有助于写单元测试。
可以在特定情况的测试中增加额外的模块,这些模块能更改配置,能帮助进行端对端的测试。
第三方代码可以作为可复用的module打包到angular中。
模块可以以任何先后或者并行的顺序加载(因为模块的执行本身是延迟的)。
定义模块
2.
服务本身是一个任意的对象。
ng提供服务的过程涉及到angular的依赖注入机制。
angular是用
例子(不常用):
3. $provide里的factory、service方法
factory方法直接把一个函数当成是一个对象的
返回的内容可以使任意类型
和factory类似,但返回的必须是对象。
4. 多个控制器内数据共享
示例:
5. 过滤器current number data
什么是angular过滤器
是用于数据的格式化,或者筛选的函数,可以直接在模板中通过一种语法使用。
筛选器:
6. 控制器的合理使用、显示、隐示的依赖注入
正确的使用controller
controller不应该尝试做太多的事情。他应仅仅包含单个视图所需要的业务逻辑。
保持controller的简单性,常见办法是抽出那些不属于controller的工作到service中,在controller通过依赖注入来使用这次service。
不要在controller中做以下的事情
1) 任何类型的DOM操作 - controller应该仅仅包含业务逻辑,任何表现逻辑放到controller中,大大地影响了应用逻辑的可测试性。angular为了自动操作(更新)DOM,提供的数据绑定。如果希望执行我们自定义的DOM操作,可以把表现逻辑抽取到directive中。
2) Input formatting(输入格式化) - 使用angular form cocntols代替。
3) Output filtering(输出格式化过滤) - 使用angular filters代替。
4) 执行无状态或有状态的、controller共享的代码 - 使用angular server代替。
5) 实例化或者管理其他组件的生命周期(例如创建一个服务实例) - 使用模块代替。
可以利用指令来扩展HTML标签,增加声明式语法来实现想做的任何事,可以对应用有特殊意义的元素和属性来替换一般的HTML标签。
1. 渲染指令
2. 内置事件指令
3. 内置节点指令
注:所有ng-指令里,除变量外的所有字符串都必须加单引号”
如何数据绑定
验证表单
显示出错信息
整个form的验证
避免提交没有验证吐过的表单
防止多次提交
Form控制变量
字段是否未更改:
字段是否更改:
字段有效:
字段无效:
字段错误信息:
input属性
Form方法
例子:
6.
ng-model是angular原生的directive。
通过require ngModel可以更深入的去处理数据的双向绑定。
ngModel里的属性
1. 简介
1.$scope里的
$apply
$digest方法
scope是一个指向应用model的object,也是表达式的执行 上下文。
scope被放置于一个类似应用的DOM结构的层次结构中。
angular是怎么知道变量发生了改变:
要知道一个变量变了,方法不外乎两种:
1.能通过固定的接口才能改变变量的值,比如说只能通过set()设置变量值,set被调用时比较一下就知道了。
2.脏检查,将元对象复制一份快照,在某个时间,比较现在对象与快照的值,如果不一样就表明发生变化,这个策略要保留两份变量,而且要遍历对象,比较每个属性,这样会有一定性能问题。
angular的策略
angular的实现是使用脏检查。
1.不会脏检查所有对象,当对象被绑定到html中,这个对象添加为检查对象(watcher)。
2.不会脏检查所有属性,同样当属性呗绑定后,这个属性被列为检查的属性。
在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了n个属性,就会添加n个watcher。
什么时候去脏检查
angular所系统的方法中都会触发比较事件,比如:controller初始化的时候,所有已ng-开头的事件执行后,都会触发脏检查。
如何手动触发脏检查
$apply仅仅只是进入angular context,然后通过
$digest去触发脏检查。
$apply如果不给参数的话,会检查改
$scope里的所有监听的属性,推荐给上参数。
$digest()
所属的
scope和其所有子
scope的脏检查,脏检查又会触发
$watch(),整个angular双向绑定机制就活了起来。
不建议直接调用
$digest(),而应该使用
$apply(),
$apply()其实不能把信直接送给
$digest,之间还有
$eval门卫把关,如果
$apply带的表达式不合法,
$eval会把错误送交
$exceptionHandler。合法才触发digest,所以更安全。
在angular.js框架文件中如何编写
$apply
$apply: function (a) { try { n("$apply"); try { return this.$eval(a) } finally { J.$$phase = null } } catch (b) { f(b) } finally { try { J.$digest() } catch (c) { throw f(c), c; } } }
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>$apply</title> </head> <body ng-app="myApp" ng-controller="My 4000 Ctrl"> <h1>{{date}}</h1> <script src="js/angular-1.5.8.min.js"></script> <script> angular.module('myApp',[]) .controller('MyCtrl',function($scope){ $scope.date=new Date(); setInterval(function(){ //可以触发脏检查 $scope.$apply(function(){ $scope.date=new Date(); }); },1000); }); </script> </body> </html>
2.
$scope里的
$watch方法
在
$digest执行时,如果watch观察的value与上次执行时不一样时,就会被触发。
AngularJS内部的watch实现了页面随吗,model的及时更新。
$watch(watchFn,watchAction,deepWatch)
watchFn:angular表达式或函数的字符串。
watchAction(newValue,oldValue,scope):watchFn发生辩护会被调用。
deepWatch:可选的布尔值命令,检查被监控的对象的每个属性是否发生变化。
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>$watch</title> </head> <body ng-app="myApp" ng-controller="MyCtrl"> <input type="text" ng-model="name"> <p>{{name}},改变了{{count}}次</p> <script src="js/angular-1.5.8.min.js"></script> <script> angular.module('myApp',[]) .controller('MyCtrl',function($scope){ $scope.name='张三'; $scope.count=0; $scope.data={ name:'李四', count:20 }; //监听一个model,当model每次改变时,都会触发这个函数 $scope.$watch('name',function(newValue,oldValue){ ++$scope.count; if($scope.count>10){ $scope.name='已经大于10次了'; } }); //true:监听整个data对象和其属性。false:只监听data对象 $scope.$watch('data',function(){ },true); }); </script> </body> </html>
2. 购物车案例
1.forEach()
angular有自己的生命周期。循环给一个 angular监听的变量复值时。最好还是用angular自带的循环方法。
angular.forEach()
var objs =[{a:1},{a:2}]; angular.forEach(objs, function(data,index,array){ //data等价于array[index] console.log(data.a+'='+array[index].a); });
参数如下:
objs:需要遍历的集合
data:遍历时当前的数据
index:遍历时当前索引
array:需要遍历的集合,每次遍历时都会把objs原样的传一次。
也可以不用写后面两个参数:
var objs =[{a:1},{a:2}]; angular.forEach(objs, function(data){ console.log(data.a); });
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> <link rel="stylesheet" href="css/bootstrap.min.css"> </head> <body ng-app="myCart" ng-controller="CartCtrl"> <div class="container"> <table class="table table-hover"> <thead> <tr> <td>编号</td> <td>名称</td> <td>数量</td> <td>单价</td> <td>总价</td> <td>操作</td> </tr> </thead> <tbody ng-hide="!cart.length"> <tr ng-repeat="item in cart"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td> <button type="button" class="btn btn-primary" ng-click="reduce(item.id)">-</button> <input type="text" value="" ng-model="item.num" readonly> <button type="button" class="btn btn-primary" ng-click="add(item.id)">+</button> </td> <td>{{item.price}}</td> <td>{{item.num*item.price}}</td> <td> <button type="button" class="btn btn-danger" ng-click="remove(item.id)">移除</button> </td> </tr> <tr> <td></td> <td>总数量:</td> <td>{{totalNum()}}</td> <td>总价格:</td> <td>{{totalPrice()}}</td> <td> <button type="button" class="btn btn-danger" ng-click="cart={}">清空购物车</button> </td> </tr> </tbody> </table> <p ng-show="!cart.length">购物车为空,快来添加产品吧~</p> </div> <script src="js/angular-1.5.8.min.js"></script> <script src="js/cart.js"></script> </body> </< 16dda span class="hljs-title">html>
//cart.js angular.module('myCart',[]) .controller('CartCtrl',function($scope){ $scope.cart=[ { id:1, name:'iphone6', num:20, price:500 }, { id:2, name:'iphone6S', num:32, price:1500 }, { id:3, name:'iphone7', num:43, price:2500 }, { id:4, name:'iphone7S', num:46, price:3500 } ]; //总价格 $scope.totalPrice=function(){ var totalPrice=0; angular.forEach($scope.cart,function(item){ totalPrice+=item.num*item.price; }); return totalPrice; }; //总数量 $scope.totalNum=function(){ var totalNum=0; angular.forEach($scope.cart,function(item){ totalNum+=parseInt(item.num); }); return totalNum; }; //找到操作的索引 var findIndex=function(id){ var index=-1; angular.forEach($scope.cart,function(item,key){ if(item.id===id){ index=key; } }); return index; }; //移除产品 $scope.remove=function(id){ var index=findIndex(id); if(index!==-1){ $scope.cart.splice(index,1); } }; //增加产品数量 $scope.add=function(id){ var index=findIndex(id); if(index!==-1){ ++$scope.cart[index].num; } }; //减少产品数量 $scope.reduce=function(id){ var index=findIndex(id); if(index!==-1){ var _num=$scope.cart[index].num; if(_num>1){ --$scope.cart[index].num; }else { if(confirm('是否移除该产品?')){ $scope.remove(id); } } } }; });
运行结果为:
3. 模块和控制器、过滤器
1. 模块和控制器什么是Module?
大部分应用都有一个主方法(main)用来实例化、组织、启动应用。
AngularJS应用没有主方法,而是使用模块来声明应用应该如何启动。
模块允许通过声明的方法来描述应用中的依赖关系,以及如何进行组装和启动。
Angular模块
模块是组织业务的一个框框,在一个模块当中定义多个服务。当引入了一个模块的时候,就可以使用这个模块提供的一种或多种服务了。
AngularJS本身的一个默认模块叫做ng,它提供了
$http,
$scope等等服务。
服务只是模块提供的多种机制中的一种,其他的还有指令(directive),过滤器(filter),及其他配置信息。
也可以在已有的模块中新定义一个服务,也可以先定义一个模块,然后在新模块中定义新服务。
服务是需要显示地声明依赖(引入)关系的,让ng自动地做注入。
Module优点
启动过程是声明式的,更容易懂。
在单元测试是不需要加载全部模块的,因此这种方式有助于写单元测试。
可以在特定情况的测试中增加额外的模块,这些模块能更改配置,能帮助进行端对端的测试。
第三方代码可以作为可复用的module打包到angular中。
模块可以以任何先后或者并行的顺序加载(因为模块的执行本身是延迟的)。
定义模块
angular.module(name,[requires],configFn);
name:模块的名称。
[requires]:需要引入的其他模块名称。
configFn:会在模块初始化时执行,可以配置模块的服务。
2.
$provide里
provider()方法
服务本身是一个任意的对象。
ng提供服务的过程涉及到angular的依赖注入机制。
angular是用
$provide对象来实现自动依赖注入机制,注入机制通过调用一个provider的
$get()方法,把得到的对象作为参数进行相关调用。
$provide.provider是一种定义服务的方法,
$provide还提供了很多很简便的方法,这些简便的方法还直接被
module所引用。
例子(不常用):
var myApp=angular.module('myApp',[],function($provide){ $provide.provider('CustomService',function(){ this.$get=function(){ return{ message:'CustomService Message' } } }) });
3. $provide里的factory、service方法
$provide.factory
factory方法直接把一个函数当成是一个对象的
$get()方法。
返回的内容可以使任意类型
$provide.service
和factory类似,但返回的必须是对象。
4. 多个控制器内数据共享
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>多个控制器共享数据</title> </head> <body> <div ng-app="myApp"> <div ng-controller="firstCtrl"> first.data<input type="text" ng-model="data.name"> first.Data<input type="text" ng-model="Data.message"> <p>first-name:{{data.name}}</p> <p>first-message:{{Data.message}}</p> </div> <div ng-controller="nextCtrl"> <p>next-name:{{data.name}}</p> <p>next-message:{{Data.message}}</p> </div> </div> <script src="js/angular-1.5.8.min.js"></script> <script> angular.module('myApp',[]) .factory('Data',function(){ return{ message:'共享的数据' } }) .controller('firstCtrl',function($scope,Data){ $scope.data={ name:'张三' }; $scope.Data=Data; }) .controller('nextCtrl',function($scope,Data){ $scope.data=$scope.$$prevSibling.data;//$$prevSibling通过当前作用域找到上一个作用域 $scope.Data=Data; }); </script> </body> </html>
5. 过滤器current number data
什么是angular过滤器
是用于数据的格式化,或者筛选的函数,可以直接在模板中通过一种语法使用。
{{expression | filter}}
{{expression | filter1 | filter2}}
{{expression | filter1:param,...}}
筛选器:
number:为数字添加分隔”,”,会更方便显示数字,如果加上数字参数,可以控制保留小数的个数。
currency:货币格式,默认为$,可以通过加参数来改变单位。
date:格式化时间,添加不同的参数可以有不同格式显示时间。查看详情。
limitTo:添加数字参数,将数组切割为所添参数个数的数组,如参数为负数可获取倒数参数个数的数组。
lowercase:将英文格式化为小写格式。
uppercase:将英文格式化为大写格式。
filter:添加参数,从数组项中查找一个子集。
orderBy:排序。
json:格式化为json格式。一般用于调试。
6. 控制器的合理使用、显示、隐示的依赖注入
正确的使用controller
controller不应该尝试做太多的事情。他应仅仅包含单个视图所需要的业务逻辑。
保持controller的简单性,常见办法是抽出那些不属于controller的工作到service中,在controller通过依赖注入来使用这次service。
不要在controller中做以下的事情
1) 任何类型的DOM操作 - controller应该仅仅包含业务逻辑,任何表现逻辑放到controller中,大大地影响了应用逻辑的可测试性。angular为了自动操作(更新)DOM,提供的数据绑定。如果希望执行我们自定义的DOM操作,可以把表现逻辑抽取到directive中。
2) Input formatting(输入格式化) - 使用angular form cocntols代替。
3) Output filtering(输出格式化过滤) - 使用angular filters代替。
4) 执行无状态或有状态的、controller共享的代码 - 使用angular server代替。
5) 实例化或者管理其他组件的生命周期(例如创建一个服务实例) - 使用模块代替。
//隐示的依赖注入 .controller('firstCtrl',function($scope){...}); //显示的依赖注入(推荐使用) .controller('nextCtrl',['$scope',function($scope){...}]); //controller方法如何依赖注入 function otherCtrl(a){...} otherCtrl.$inject=['$scope'];
4. 内置渲染指令、自定义指令
什么是指令可以利用指令来扩展HTML标签,增加声明式语法来实现想做的任何事,可以对应用有特殊意义的元素和属性来替换一般的HTML标签。
1. 渲染指令
ng-init:初始化数据
ng-bind:绑定数据
ng-repeat
ng-include:添加地址参数,调用另一个静态页
ng-bind-template:绑定模板
2. 内置事件指令
ng-change
ng-click
ng-dbclick
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-submit
3. 内置节点指令
ng-style:先在控制器中定义一个样式:
$scope.defaultStyle={color:'red','margin-top':'50px'};再应用在页面上:
<div ng-style="defaultStyle">
ng-class:当表达式为真时添加某个class。例:
ng-class="{ red:status }",当
status为真时,为元素添加red类,为假时去掉red类
ng-class-even:当前行是偶数行时添加某个class。例:
ng-class-even="'evenRow'"
ng-class-odd:当前行是奇数行是添加某个calss 。 例:
ng-class-odd="'oddRow'"
ng-show:为真时显示。例:
<div ng-show="status">status为真时显示</div>
ng-hide:为真时隐藏。
ng-switch:选择表达式。例子:
<ul ng-switch on="status"> <li ng-switch-when="true"> true </li> <li ng-switch-when="false"> false </li> </ul>
ng-src:表达式作为图片url,例:
<img ng-src="{{src}}">
ng-href:表达式作为url
ng-if:为真时显示:
<div ng-if="status">为真时显示</div>
注:所有ng-指令里,除变量外的所有字符串都必须加单引号”
5. 表单、自定义表单
一般来讲表单可能遇到的问题:如何数据绑定
验证表单
显示出错信息
整个form的验证
避免提交没有验证吐过的表单
防止多次提交
Form控制变量
字段是否未更改:
formName.inputFieldName.$pristine
字段是否更改:
formName.inputFieldName.$dirty
字段有效:
formName.inputFieldName.valid
字段无效:
formName.inputFieldName.$invalid
字段错误信息:
formName.inputFieldName.$error
input属性
name:名字
ng-model:绑定的数据
ng-required:是否必填
ng-minlength:最小长度
ng-maxlength:最大长度
ng-pattern:匹配模式
ng-change:值变化时的回调
Form方法
$setPristine将表单复位原始状态,
class,
$dirty,
$spristine
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>表单验证</title> <link rel="stylesheet" href="css/bootstrap.min.css"> </head> <body> <div ng-app="myApp" style="margin-top: 50px;"> <form name="myForm" ng-controller="myCtrl" class="container form-horizontal" action="register.php" method="post"> <!-- 用户名 --> <div class="form-group"> <label class="col-sm-2 control-label">用户名</label> <div class="col-sm-10" ng-class="{'has-error':myForm.username.$invalid && myForm.username.$dirty && myForm.username.$pristine}"> <input type="text" name="username" autocomplete="off" ng-model="data.username" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="用户名"> <div ng-show="myForm.username.$error.maxlength" class="alert alert-danger help-block">用户名长度不能超过10位</div> <div ng-show="myForm.username.$error.minlength" class="alert alert-danger help-block">用户名长度不能小于5位</div> <div ng-show="myForm.username.$error.pattern" class="alert alert-danger help-block">用户名必须为英文字母开始</div> </div> </div> <!-- 密码 --> <div class="form-group"> <label class="col-sm-2 control-label">密码</label> <div class="col-sm-10" ng-class="{'has-error':myForm.psd.$invalid && myForm.psd.$dirty && myForm.username.$pristine}"> <input type="password" name="psd" autocomplete="off" ng-model="data.psd" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="密码"> <div ng-show="myForm.psd.$error.maxlength" class="alert alert-danger help-block">用户名长度不能超过10位</div> <div ng-show="myForm.psd.$error.minlength" class="alert alert-danger help-block">用户名长度不能小于5位</div> <div ng-show="myForm.psd.$error.pattern" class="alert alert-danger help-block">用户名必须为英文字母开始</div> </div> </div> <!-- 确认密码 --> <div class="form-group"> <label class="col-sm-2 control-label">确认密码</label> <div class="col-sm-10" ng-class="{'has-error':myForm.psdConfirm.$invalid && myForm.psdConfirm.$dirty && myForm.psdConfirm.$pristine}"> <input type="password" name="psdConfirm" autocomplete="off" ng-model="data.psdConfirm" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="确认密码"> <div ng-show="myForm.psd.$dirty && myForm.psdConfirm.$dirty && data.psdConfirm!=data.psd" class="alert alert-danger help-block">两次密码不一致</div> </div> </div> <!-- 邮箱 --> <div class="form-group"> <label class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10" ng-class="{'has-error':myForm.email.$invalid && myForm.email.$dirty && myForm.email.$pristine}"> <input type="email" name="email" autocomplete="off" ng-model="data.email" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="邮箱"> <div ng-show="myForm.email.$error.email" class="alert alert-danger help-block">邮箱格式不正确</div> </div> </div> <!-- 网址 --> <div class="form-group"> <label class="col-sm-2 control-label">博客</label> <div class="col-sm-10" ng-class="{'has-error':myForm.blog.$invalid && myForm.blog.$dirty && myForm.blog.$pristine}"> <input type="url" name="blog" autocomplete="off" ng-model="data.blog" ng-required="true" ng-pattern="/^[a-zA-Z]{1}/" class="form-control" placeholder="博客"> <div ng-show="myForm.url.$error.url" class="alert alert-danger help-block">博客地址格式不正确</div> </div> </div> <!-- 年龄 --> <div class="form-group"> <label class="col-sm-2 control-label">年龄</label> <div class="col-sm-10" ng-class="{'has-error':myForm.age.$invalid && myForm.age.$dirty && myForm.age.$pristine}"> <input type="number" name="age" autocomplete="off" ng-model="data.age" ng-required="true" min="10" max="99" class="form-control" placeholder="年龄"> <div ng-show="myForm.age.$error.min" class="alert alert-danger help-block">年龄不能小于10岁</div> <div ng-show="myForm.age.$error.max" class="alert alert-danger help-block">年龄不能大于99岁</div> </div> </div> <!-- 性别 --> <div class="form-group"> <label class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" ng-required="true" name="sex" ng-model="data.sex" value="1"> 男 </label> <label class="radio-inline"> <input type="radio" name="sex" ng-model="data.sex" value="0"> 女 </label> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">爱好</label> <div class="col-sm-10"> <label class="checkbox-inline" ng-repeat="hobby in hobbies"> <input type="checkbox" name="hobby[]" ng-checked="data.hobbies==undefined ? false:data.hobbies.indexOf(hobby.id)!==-1" ng-click="hobbySelect(hobby.id)"> {{hobby.name}} </label> </div> </div> <!-- 城市 --> <div class="form-group"> <label class="col-sm-2 control-label">出生地</label> <div class="col-sm-3"> <select class="form-control" ng-required="true" ng-change="data.area=false" ng-model="data.province" ng-options="x.id as x.name for x in cities | cityFilter:0"></select> </div> <div class="col-sm-3"> <select class="form-control" ng-required="true" ng-show="data.province" ng-model="data.area" ng-options="x.id as x.name for x in cities | cityFilter:data.province"></select> </div> <div class="col-sm-3"> <select class="form-control" ng-required="true" ng-show="data.province && data.area" ng-model="data.city" ng-options="x.id as x.name for x in cities | cityFilter:data.area"></select> </div> </div> <!-- 提交 --> <div class="form-group"> <div class="col-sm-10 col-sm-offset-2"> <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid || data.hobbies===undefined || data.hobbies.length===0">注册</button> <button type="reset" class="btn btn-info" ng-click="reset()">重置</button> </div> </div> </form> </div> <script src="js/angular-1.5.8.min.js"></script> <script src="js/form.js"></script> </body> </html>
//form.js angular.module('myApp',[]) //三级关联城市过滤器 .filter('cityFilter',function(){ return function (data,parent){ var filterData=[]; angular.forEach(data,function(obj){ if(obj.parent===parent){ filterData.push(obj); } }); return filterData; } }) .controller('myCtrl',['$scope',function($scope){ var that=this; $scope.hobbies=[ { id:1, name:'跑步' }, { id:2, name:'打台球' }, { id:3, name:'打羽毛球' } ]; $scope.cities=[ { name:'上海', parent:0, id:1 }, { name:'上海市', parent:1, id:2 }, { name:'徐家汇', parent:2, id:8 }, { name:'徐汇区', parent:2, id:5 }, { name:'长宁区', parent:2, id:3 }, { name:'北京', parent:0, id:4 }, { name:'北京市', parent:4, id:5 }, { name:'东城区', parent:5, id:6 }, { name:'丰台区', parent:5, id:7 }, { name:'浙江', parent:0, id:9 }, { name:'杭州', parent:9, id:100 }, { name:'宁波', parent:100, id:66 }, { name:'西湖区', parent:100, id:35 } ]; $scope.data={ hobbies:[1,2], city:66 }; //重置,先克隆原始数据 $scope.origData=angular.copy($scope.data);//如果使用$scope.origData=$scope.data,那么data变化,origData也会变化 $scope.reset=function(){ $scope.data=angular.copy($scope.origData);//再将已经克隆的数据赋给data that.initCity();//重新调用城市 $scope.myForm.$setPristine();//将表单复位为原始状态 }; //爱好 $scope.hobbySelect=function(id){ var index=-1; if($scope.data.hobbies==undefined){ $scope.data.hobbies=[]; }else { index=$scope.hobbies.indexOf(id); } if(index===-1){ $scope.data.hobbies.push(id); }else{ $scope.data.hobbies.splice(index,1); } }; //让城市关联起来 this.findCityId=function(parent){ var parentId; angular.forEach($scope.cities,function(city){ if(city.id===parent){ parentId=city.parent; } }); return parentId; }; //根据默认的城市查找前两级 this.initCity=function(){ if($scope.data.city!==undefined){ $scope.data.area=this.findCityId($scope.data.city); $scope.data.province=this.findCityId($scope.data.area); } }; this.initCity(); }]);
6. ng-model
ng-model是angular原生的directive。通过require ngModel可以更深入的去处理数据的双向绑定。
ngModel里的属性
$parsers属性保存了从viewValue向modelValue绑定过程中的处理函数,它们将来会依次执行。
$formattters它保存的是从modelValue向viewValue绑定过程中的处理函数。
$setViewValue当view发生了某件事情时,从view向model绑定调用
$setViewValue把viewValue保存下来。
$render当模型发生变化时,应该怎么去更新视图,从model向view绑定,调用
ctrl.$render方法,将viewValue渲染到页面上。
$serValidity设置验证结果。
$viewValue视图的值。
modelValue模型里的值。
相关文章推荐
- angularJS 学习笔记3 injector创建过程
- AngularJs学习笔记--bootstrap
- angularjs学习笔记
- Angularjs 学习笔记总结之二
- AngularJS学习笔记三 作用域
- AngularJS学习笔记
- AngularJS 学习笔记 (三)
- Angularjs_学习笔记
- Angularjs学习笔记--ui-Router
- angularjs学习笔记 ng-class
- 学习笔记-AngularJs(八)
- angularjs学习笔记之directive的返回对象属性(一)
- angularjs学习笔记--作用域
- Angularjs学习笔记1_基本技巧
- AngularJs学习笔记__5、内置过滤器
- AngularJs学习笔记--Understanding the Model Component
- AngularJs学习笔记[01]——数据绑定
- AngularJs学习笔记--Understanding Angular Templates
- Angularjs 学习笔记
- AngularJS基础学习笔记之简单介绍