AngularJS双向数据绑定
一、概念
AngularJS中,只关心数据,数据的变化会自动引起视图的变化。并且视图是局部刷新的,不是整个页面刷新的,AngularJS会自动识别哪里用到了这个更新的数据,即脏数据检查。
我们可以把控制器中的数据表现在视图上,也可以更新视图来改变控制器中的数据。
最简单的更新视图的方法就是表单元素,AngularJS中提出了two-way databinding双向数据绑定的技术,让视图和控制器中的数据实时双向绑定。
<!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="../libs/angular.js/1.3.2/angular.js"></script> </head> <body> <div ng-controller="MainController as mc"> <h1>{{ mc.name }}</h1> <!-- 只有表单元素才允许使用ng-model指令 --> <input type="text" ng-model="mc.name"> </div> <script type="text/javascript"> var myapp = angular.module("myapp",[]); //第二个参数是数组,表示依赖注入 myapp.controller("MainController", [function () { this.name = "我爱中国"; }]); </script> </body> </html>
效果图如下:

小结:
所有表单控件都可以使用ng-model指令来与控制器中的某一个值进行双向数据绑定,指的是:
① 当控制器中的值变化时,控件中的值也跟着变化
② 当控件中的值变化时,控制器中的值也跟着变化
二、案例1:调色板
代码如下:
<!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>调色板</title> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid #333; } </style> <script type="text/javascript" src="../libs/angular.js/1.3.2/angular.js"></script> </head> <!-- 实例化控制器MainController,起个别名mc --> <body ng-controller="MainController as mc"> <h2>{{ mc.name }}</h2> <div class="box" ng-style="mc.color()"></div> R:<input type="range" min="0" max="255" ng-model="mc.r"> <input type="text" ng-model="mc.r"> <br/> G:<input type="range" min="0" max="255" ng-model="mc.g"> <input type="text" ng-model="mc.g"><br/> B:<input type="range" min="0" max="255" ng-model="mc.b"> <input type="text" ng-model="mc.b"> <script type="text/javascript"> var myapp = angular.module("myapp", []); myapp.controller("MainController", [function () { this.name = "我的调色板"; this.r = 100; this.g = 100; this.b = 100; //这样写,不会生效,需要改成函数的形式,同时ng-style="mc.color"改为ng-style="mc.color()",这是angularjs规定的 // this.color = { // "background-color": "rgb(" + this.r + ", 100, 100)" // }; this.color = function () { return { "background-color": "rgb(" + this.r + ", " + this.g + ", " + this.b + ")" }; }; }]); </script> </body> </html>
运行效果:

这里, 如果把type="text"替换为type="number",滑动块时,会出现如下错误:

如何解决?
小结:
a. 我们的程序没有一行关于DOM的,因为关于DOM的语句已经暗含到HTML标签上面的“指令”上面了.
b. 这个例子里面,学习了一个内置指令(事实上AngularJS对HTML的升级就是体现在发明了很多内置指令上)ng-style:
ng-style指令表示给HTML元素加上动态样式(从控制器中读取值的样式),此时感觉是历史的倒退,因为好不容易把HTML和CSS分开,AngularJS又给合上了。
c. 如果控制器中的某一个值,由其他值决定,并且希望其他值改变的时候,这个值也能改变,此时要写成函数return的形式。


三、案例2:模拟微博发布
需求:发微博限制140字,能够实时提醒用户写了多少字,例如,75/140字。当超过140字的时候数字变红,同时发布按钮不能点击。
分析:AngularJS的世界不能操作DOM,一切都要控制数据。Angular、React、Vue等等都是不直接操作DOM,去jQuery化。
<!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>模拟微博发布</title> <script type="text/javascript" src="../libs/angular.js/1.3.2/angular.js"></script> </head> <!--实例化控制器MainController--> <body ng-controller="MainController as mc"> <h3>{{ mc.name }}</h3> <p> <textarea cols="30" rows="10" ng-model="mc.txt"></textarea> <!--<span ng-style="{'color': 'red'}">{{ mc.txt.length }}/140字</span>--> <span ng-style="mc.getColor()">{{ mc.txt.length }}/140字</span> </p> <p> <input type="button" value="发布" ng-disabled="mc.txt.length > 140 || mc.txt.length == 0"/> <input type="button" value="清空" ng-click="mc.reset()" ng-disabled="mc.txt.length == 0"/> </p> <script> var myapp = angular.module("myapp", []); myapp.controller("MainController", [function () { this.name = "微博发布"; //这里也可以不定义 this.txt = ""; //颜色 var self = this; this.getColor = function () { return self.txt.length > 140 ? { "color" : "red" } : { "color" : "#333" } }; //清空 this.reset = function () { this.txt = ""; }; }]); </script> </body> </html>
效果如下图:

小结:
a. ng-disabled指令:可以让disabled属性变得“智能”、“动态化”,可以根据值来决定它的true或false,此时ng-disabled中可以写表达式,例如本例中的mc.txt.length > 140或者写函数。
b. 本例中涉及到的数据只有文本这个东西(mc.txt),其他的字数提示、字数提示的颜色、发布按钮是否禁用等等 都是根据它的length来决定的。
四、案例3:模拟表格
需求:不使用AJAX与服务器交互,假设数据已经取到浏览器本地,需要呈现在页面上。
<!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>模拟表格</title> <style type="text/css"> .table_wrap { width: 600px; margin: 0 auto; } table, tr, th, td { border-bottom: 1px solid #333; border-collapse: collapse; } th, td { width: 20%; line-height: 150%; } tr:nth-child(2n) { background-color: #eee; } </style> <script type="text/javascript" src="../libs/angular.js/1.3.2/angular.js"></script> </head> <body ng-controller="MainController as mc"> <div class="table_wrap"> <table width="600"> <tr> <th>学号</th> <th>姓名</th> <th>语文成绩</th> <th>数学成绩</th> <th>英语成绩</th> </tr> <tr ng-repeat="item in mc.data"> <td>{{ item.sid }}</td> <td>{{ item.name }}</td> <td>{{ item.yuwen }}</td> <td>{{ item.shuxue }}</td> <td>{{ item.yingyu }}</td> </tr> </table> </div> <script> var myapp = angular.module("myapp", []); //定义控制器 myapp.controller("MainController", [function () { //定义数据:数组 this.data = [ {"sid": 1001, "name": "小明", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1002, "name": "小洪", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1003, "name": "小亮", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1004, "name": "小蓝", "yuwen": 99, "shuxue": 100, "yingyu":98} ]; }]); </script> </body> </html>
使用ng-repeat指令来重复一个HTML标签,语法如下:
<div ng-repeat="变量名 in 数组数据"></div>
此时,这个变量将按顺序自动去迭代数组数据中的每一项。
效果如下图:

WebStorm小技巧:按住alt键 鼠标选择一列,然后输入文字就会编辑多行,这个功能很赞,比较实用
接下来,我们在网页上实现增、删、排序功能,实现如下效果:

涉及js数组的添加、删除、排序方法
代码如下:
<!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>模拟表格</title> <style type="text/css"> .table_wrap { width: 600px; margin: 0 auto; } table, tr, th, td { border-bottom: 1px solid #333; border-collapse: collapse; } th, td { width: 20%; line-height: 150%; } tr:nth-child(2n) { background-color: #eee; } .form_box { background-color: skyblue; padding: 10px; width: 400px; } </style> <script type="text/javascript" src="../libs/angular.js/1.3.2/angular.js"></script> </head> <body ng-controller="MainController as mc"> <div class="table_wrap"> <table width="600"> <tr> <th ng-click="mc.changeSort('sid')">学号<span ng-show="mc.sortBy == 'sid'">{{ mc.sign() }}</span></th> <th ng-click="mc.changeSort('name')">姓名<span ng-show="mc.sortBy == 'name'">{{ mc.sign() }}</span></th> <th ng-click="mc.changeSort('yuwen')">语文<span ng-show="mc.sortBy == 'yuwen'">{{ mc.sign() }}</span></th> <th ng-click="mc.changeSort('shuxue')">数学<span ng-show="mc.sortBy == 'shuxue'">{{ mc.sign() }}</span></th> <th ng-click="mc.changeSort('yingyu')">英语<span ng-show="mc.sortBy == 'yingyu'">{{ mc.sign() }}</span></th> <th>操作</th> </tr> <tr ng-repeat="item in mc.data"> <td>{{ item.sid }}</td> <td>{{ item.name }}</td> <td>{{ item.yuwen }}</td> <td>{{ item.shuxue }}</td> <td>{{ item.yingyu }}</td> <td><input type="button" value="删除" ng-click="mc.remove(item.sid)"></td> </tr> </table> </div> <div class="form_box"> <p> 结果:{{ mc.formobj }} </p> <p> 学号:<input type="text" ng-model="mc.formobj.sid"/> </p> <p> 姓名:<input type="text" ng-model="mc.formobj.name"/> </p> <p> 语文:<input type="text" ng-model="mc.formobj.yuwen"/> </p> <p> 数学:<input type="text" ng-model="mc.formobj.shuxue"/> </p> <p> 英语:<input type="text" ng-model="mc.formobj.yingyu"/> </p> <p><input type="button" value="添加" ng-click="mc.add()"></p> </div> <script> var myapp = angular.module("myapp", []); //定义控制器 myapp.controller("MainController", [function () { //定义数据:数组 this.data = [ {"sid": 1001, "name": "小明", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1002, "name": "小洪", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1003, "name": "小亮", "yuwen": 99, "shuxue": 100, "yingyu":98}, {"sid": 1004, "name": "小蓝", "yuwen": 99, "shuxue": 100, "yingyu":98} ]; //定义表单对象 this.formobj = {}; //添加 let self = this; this.add = function () { self.data.push(self.formobj); }; //删除 this.remove = function (sid) { self.data.forEach(function (value, key, ownerArr) { if(value.sid == sid){ self.data.splice(key, 1); } }); } //排序字段 this.sortBy = 'name'; //排序方式 asc=true 升序 asc=false降序 this.asc = true; //排序符号 this.sign = function () { return self.asc == true ? "↑" : "↓"; }; this.changeSort = function (sortBy) { if(sortBy == self.sortBy) { self.asc = !self.asc; } else { self.sortBy = sortBy; } //排序 self.data.sort(function (a, b) { if(a[self.sortBy] > b[self.sortBy]) { return self.asc ? 1 : -1; } else { return self.asc ? -1 : 1; } }); } }]); </script> </body> </html>
五、案例4:省市县联动
浙公网安备 33010602011771号