angular数据绑定与监控(学习笔记)
2016-02-04 18:13
701 查看
数据的双向绑定
angular实现了双向绑定机制,所谓双向绑定,就是从界面的操作能实时反映到数据,数据的变更能实时展现到界面.基于单一模型的界面同步
ng-model 指令:可以将输入域的值与 AngularJS 创建的变量绑定。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" > <span style="white-space:pre"> </span>名字: <input ng-model="name"> <br/>{{name}}</div> <script> var app = angular.module('myApp', []); </script> </body> </html>
在angular中,变量和表达式都依附在一种叫做作用域(scope)的东西上.每个angular应用默认会有一个根作用域($rootScope),如果在界面中绑定未定义的变量,当它被赋值的时候,就会自动创建到对应的作用域上.
"{{}}"这种符号,称为插值表达式,这里面的内容将会被动态解析.除了"{{}}"angular还提供了ng-bind来实现一样的功能.
对模型的二次解析
有的时候,我们需要在界面上显示性别,男/女,但是在数据库里面存的是0或者1,那么我们就要对它进行一些转换.<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <div>{{formatGender(tom.gender)}}</div> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.tom = { name: "Tom", gender: 1, genderText: "男" }; $scope.formatGender = function(gender) { if (gender == 0){ return "女"; } if (gender == 1){ return "男"; } }; }); </script> </body> </html>
我们这里利用表达式使用函数的方法对数据进行格式化,其实只是作用于视图层,不会影响到真实数据模型.
注意:
1:在绑定表达式里面,只能使用自定义函数,不能使用原生函数.
<div>{{Math.abs(-1)}}</div>
以上是错误的例子,如果确实需要调用原生函数,可以用一个自定义函数作包装,在自定义函数里面可以随意使用各种原生对象.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <div>{{abs(-1)}}</div> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.abs = function(number) { return Math.abs(number); }; }); </script> </body> </html>
2:上面这个格式化数据的例子只是为了说明可以这么用,但不表示这是最佳方案.angular为这类需求提供了filter方案,可以在"{{}}"表达式中使用管道操作符来格式化数据.
{{expression | filterName : parameter1 : ...parameterN}}
数组与对象结构的绑定
有的时候,我们需要把一个数组的数据展示出来,这可以使用ng-repeat指令来处理,它相当于一个循环.单一数组数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="add()">Add Item</button> <ul> <li ng-repeat="item in arr1">{{item}}</li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.arr1 = [1, 2, 3]; $scope.add = function() { $scope.arr1.push($scope.arr1.length + 1); }; }); </script> </body> </html>
这样就可以把数组的内容展示到界面上.数组中的数据变化时,也能实时更新到界面上来.
但有时候,我们会遇到数组里有重复元素的情况,这时候,ng-repeat代码就不能起作用,原因是angular默认需要在数组中使用唯一索引,如果这遇到这情况,那就可以指定它使用序号作为索引即可.
含有重复值的数组数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="add()">Add Item</button> <ul> <li ng-repeat="item in arr1 track by $index">{{item}}</li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.arr1 = [1,1,1,1, 2, 3]; $scope.add = function() { $scope.arr1.push($scope.arr1.length + 1); }; }); </script> </body> </html>
多维数组
可以用多层循环方式迭代出来:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul> <li ng-repeat="childArr in arr3 track by $index"> {{$index}} <ul> <li ng-repeat="item in childArr track by $index">{{item}}</li> </ul> </li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.arr3 = [ [11, 12, 13], [21, 22, 23], [31, 32, 33] ]; }); </script> </body> </html>
数组元素是对象
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <table class="table table-bordered"> <thead> <tr> <th>Name</th> <th>Age</th> </tr> </thead> <tbody> <tr ng-repeat="child in arr4"> <td>{{child.name}}</td> <td>{{child.age}}</td> </tr> </tbody> </table> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.arr4 = [{ name: "Tom", age: 5 }, { name: "Jerry", age: 2 }]; }); </script> </body> </html>
遍历对象属性
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul> <li ng-repeat="(key, value) in obj">{{key}}: {{value}}</li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.obj = { a: 1, b: 2, c: 3 }; }); </script> </body> </html>
如果单纯想要值,也可以不用这么麻烦,直接用数组的写法即可,就算有对象值重复,也不用像数组那样需要指定$index做索引,因为它是对象的key来做索引的,这是不会重复的.你见过两个同名的属性?
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul> <li ng-repeat="key in obj"> {{key}}</li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.obj = { a: 1, b: 2, c: 3 }; }); </script> </body> </html>
数据监控
有时候,我们不是直接把数据绑定到界面上,而是先要赋值到其他变量上,或者针对数据的变更,做出一些逻辑的处理,这时候就要用到监控.简单监控的例子
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="changeA()">click me</button> //{{a}} </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.a = 1; $scope.$watch("a", function(newValue, oldValue) { alert(oldValue + " -> " + newValue); }); $scope.changeA = function() { $scope.a++; }; }); </script> </body> </html>
对作用域上的变量添加监控后,就可以在变量变更时候得到通知了.如果说新赋值的变量和原先的相同,这个监控就不会被执行.
以上这种方式可以监控到最直接的赋值,包括各种基本类型,以及复杂类型的引用赋值,比如说下面这个数组被重新赋值了,就可以被监控到:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="changeArr()">click me</button> {{a}} </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.arr = [0]; $scope.$watch("arr", function(newValue) { alert("change:" + newValue.join(",")); }); $scope.changeArr = function() { $scope.arr = [7, 8]; }; }); </script> </body> </html>
但这种监控方式只能处理引用相等的判断,对于一些更复杂的监控,需要更细致的处理。比如说,我们有可能需要监控一个数组,但并非监控它的整体赋值,而是监控其元素的变更:
$scope.$watch("arr", function(newValue) { alert("deep:" + newValue.join(",")); }, true); $scope.addItem = function() { $scope.arr.push($scope.arr.length); };
注意,这里我们在$watch函数中,添加了第三个参数,这个参数用于指示对数据的深层监控,包括数组的子元素和对象的属性等等。
样式的数据绑定
以上我们提到的例子,都是跟数据同步,数据展示相关,但数据绑定的功能远不止于此.我们再来一个例子:
有个数据表,点中其中某条,这条就改变样式.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> <style> ul{list-style:none} .active{ color:red } </style> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul class="list-group"> <li ng-repeat="item in items" ng-class="{true:' active', false: ' '}[item==selectedItem]" ng-click="select(item)"> {{item.title}} </li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.items = []; for (var i=0; i<10; i++) { $scope.items.push({ title:i }); } $scope.selectedItem = $scope.items[0];//默认为第一项 $scope.select = function(item) { $scope.selectedItem = item;//一点击就把传入的item赋值给selectedItem }; }); </script> </body> </html>
本例中我们使用一个循环来迭代数组中的元素,并且使用一个变量selectedItem用于标识选中项.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <input type="number" ng-model="x" ng-init="x=12"/> <div ng-style="{'font-size': x+'pt'}"> 测试字体大小 </div> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { }); </script> </body> </html>
除了使用ng-class,还可以用ng-style来对样式进行控制.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> <style> ul{list-style:none} .active{ color:red } </style> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <input type="number" ng-model="x" ng-init="x=12"/> <div ng-style="{'font-size': x+'pt'}"> 测试字体大小 </div> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { }); </script> </body> </html>
状态控制
有时候,我们除了控制普通的样式,还可以控制某个界面元素的显示隐藏,我们用ng-class或者ng-style,当然也可以控制元素的显示隐藏,但angular给我们提供了一种快捷方式,那就是ng-show/ng-hide.利用数据绑定,我们可以很容易实现原有的一些显示隐藏功能.
<button ng-show="selectedItem">有选中项的时候可以点我</button> <button ng-hide="selectedItem">没有选中项的时候可以点我</button>
流程控制
除了使用ng-show/ng-hide来控制元素的显示隐藏,还可以使用ng-if.所谓的show和hide,意味着DOM元素已经存在,只是控制了是否显示,而if则起到了流程控制的作用,只有符合条件的DOM元素才会被创建,否则不创建。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul> <li ng-if="condition==1">if 1</li> <li ng-if="condition==2">if 2</li> <li ng-show="condition==1">show 1</li> <li ng-show="condition==2">show 2</li> </ul> <button ng-click="change()">change</button> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.condition = 1; $scope.change = function() { $scope.condition = 2; }; }); </script> </body> </html>
这个例子初始时候,就创建了3个li,其中一个被隐藏(show2),点击按钮,仍然是3个li,其中,if1被销毁了,if2被创建出来了,show1被隐藏了,show2显示出来了.
所以,我们看到ng-if的节点是动态创建出来的,与此类似,还有ng-switch指令:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <div ng-switch="condition"> <div ng-switch-when="A">A</div> <div ng-switch-when="B">B</div> <div ng-switch-default>default</div> </div> <button ng-click="a()">A</button> <button ng-click="b()">B</button> <button ng-click="c()">C</button> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.condition = ""; $scope.a = function() { $scope.condition = "A"; }; $scope.b = function() { $scope.condition = "B"; }; $scope.c = function() { $scope.condition = "C"; }; }); </script> </body> </html>
数据联动
最典型的例子就是省市县三级联动.我们来看这样一个例子:
有两个表,第一个的数据变动,对第二个的数据产生过滤.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> <span style="white-space:pre"> </span><style> <span style="white-space:pre"> </span>.active{color:red} <span style="white-space:pre"> </span></style></head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul class="list-group"> <li ng-repeat="province in provinceArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[province==selectedProvince]" ng-click="selectProvince(province)"> {{province}} </li> </ul> <ul class="list-group"> <li ng-repeat="city in cityArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[city==selectedCity]" ng-click="selectCity(city)"> {{city}} </li> </ul> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.provinceArr = ["江苏", "云南"]; $scope.cityArr = []; $scope.$watch("selectedProvince", function(province) {//监听<span style="font-family: Arial, Helvetica, sans-serif;">selectedProvince值的</span>变化 // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 switch (province) { case "江苏": { $scope.cityArr = ["南京", "苏州"]; break; } case "云南": { $scope.cityArr = ["昆明", "丽江"]; break; } } }); $scope.selectProvince = function(province) { $scope.selectedProvince = province; //选中给样式 }; $scope.selectCity = function(city) { $scope.selectedCity = city;//选中给样式 }; }); </script> </body> </html><!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> <span style="white-space:pre"> </span><style> <span style="white-space:pre"> </span>.active{color:red} <span style="white-space:pre"> </span></style> <span style="white-space:pre"> </span></head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <ul class="list-group"> <li ng-repeat="province in provinceArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[province==selectedProvince]" ng-click="selectProvince(province)"> {{province}} </li> </ul> <ul class="list-group"> <li ng-repeat="city in cityArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[city==selectedCity]" ng-click="selectCity(city)"> {{city}} </li> </ul> <span style="white-space:pre"> </span> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.provinceArr = ["江苏", "云南"]; $scope.cityArr = []; $scope.$watch("selectedProvince", function(province) {//监听selectedProvince值的变化 // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 switch (province) { case "江苏": { $scope.cityArr = ["南京", "苏州"]; break; } case "云南": { $scope.cityArr = ["昆明", "丽江"]; break; } } }); $scope.selectProvince = function(province) { $scope.selectedProvince = province; //选中给样式 }; $scope.selectCity = function(city) { $scope.selectedCity = city;//选中给样式 }; <span style="white-space:pre"> </span> }); </script> </body> </html>
如果绑定到下拉框上,代码更简单
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <body> <div ng-app="myApp" ng-controller="myCtrl"> <select class="form-control col-md-6" ng-model="selectedProvince" ng-options="province for province in provinceArr"></select> <select class="form-control col-md-6" ng-model="selectedCity" ng-options="city for city in cityArr"></select> <span style="white-space:pre"> </span> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.provinceArr = ["江苏", "云南"]; $scope.cityArr = []; $scope.$watch("selectedProvince", function(province) {//监听selectedProvince值的变化 // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 switch (province) { case "江苏": { $scope.cityArr = ["南京", "苏州"]; break; } case "云南": { $scope.cityArr = ["昆明", "丽江"]; break; } } }); <span style="white-space:pre"> </span> }); </script> </body> </html>
从这个例子,我们看到,相比传统前端开发方式那种手动监听事件,手动更新DOM的方式,使用angular数据绑定做数据联动真的太容易了.如果把这个例子改造成三级联动,只需要对selectedCity也做一个监控就可以了.
小结
刚刚我们已经看到数据绑定的各种使用场景了,数据绑定一切的核心就是数据.数据变更导致页面的更新,如果我们想要更新界面,只需修改数据即可.来自
https://github.com/xufei/blog/issues/14
相关文章推荐
- Apache与tomcat整合方法
- 关于docker容器是怎样建立新的namespace的。
- Ubuntu 15.10配置OpenCV
- Ubuntu 15.10配置OpenCV
- nginx域名重定向遇到的问题
- 异常__Could not publish server configuration for Tomcat v8.0 Server at localhost. Multiple Contexts ha
- 合并svn分支到主干(linux)
- centos配置amp环境
- CentOS安装rar、unrar解压缩软件的方法
- linux下定时删除指定目录下指定时间前的文件
- Hadoop学习路线图(推荐博客为主)
- gearman 监控
- LINUX SHELL遍历日期(指定输入两个日期)
- Linux性能分析的前60秒
- 利用docker搭建测试环境--安装
- apache常见问题
- Apache2.4+tomcat7.0 配置反向代理和负载均衡及session集群
- 网站常见的反爬虫和应对方法
- optimize table的一个小问题
- 我的android项目架构