AngularJS入门教程之双向绑定详解


Posted in Javascript onAugust 18, 2016

在这一步你会增加一个让用户控制手机列表显示顺序的特性。动态排序可以这样实现,添加一个新的模型属性,把它和迭代器集成起来,然后让数据绑定完成剩下的事情。

请重置工作目录:

git checkout -f step-4

你应该发现除了搜索框之外,你的应用多了一个下来菜单,它可以允许控制电话排列的顺序。

步骤3和步骤4之间最重要的不同在下面列出。你可以在GitHub里看到完整的差别。

模板

app/index.html

Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
 <option value="name">Alphabetical</option>
 <option value="age">Newest</option>
</select>


<ul class="phones">
 <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
  {{phone.name}}
  <p>{{phone.snippet}}</p>
 </li>
</ul>

我们在index.html中做了如下更改:

首先,我们增加了一个叫做orderProp的<select>标签,这样我们的用户就可以选择我们提供的两种排序方法。

然后,在filter过滤器后面添加一个orderBy过滤器用其来处理进入迭代器的数据。orderBy过滤器以一个数组作为输入,复制一份副本,然后把副本重排序再输出到迭代器。

AngularJS在select元素和orderProp模型之间创建了一个双向绑定。而后,orderProp会被用作orderBy过滤器的输入。

正如我们在步骤3中讨论数据绑定和迭代器的时候所说的一样,无论什么时候数据模型发生了改变(比如用户在下拉菜单中选了不同的顺序),AngularJS的数据绑定会让视图自动更新。没有任何笨拙的DOM操作!

控制器

app/js/controllers.js:

function PhoneListCtrl($scope) {
 $scope.phones = [
  {"name": "Nexus S",
   "snippet": "Fast just got faster with Nexus S.",
   "age": 0},
  {"name": "Motorola XOOM™ with Wi-Fi",
   "snippet": "The Next, Next Generation tablet.",
   "age": 1},
  {"name": "MOTOROLA XOOM™",
   "snippet": "The Next, Next Generation tablet.",
   "age": 2}
 ];

 $scope.orderProp = 'age';
}

我们修改了phones模型—— 手机的数组 ——为每一个手机记录其增加了一个age属性。我们会根据age属性来对手机进行排序。

我们在控制器代码里加了一行让orderProp的默认值为age。如果我们不设置默认值,这个模型会在我们的用户在下拉菜单选择一个顺序之前一直处于未初始化状态。

现在我们该好好谈谈双向数据绑定了。注意到当应用在浏览器中加载时,“Newest”在下拉菜单中被选中。这是因为我们在控制器中把orderProp设置成了‘age'。所以绑定在从我们模型到用户界面的方向上起作用——即数据从模型到视图的绑定。现在当你在下拉菜单中选择“Alphabetically”,数据模型会被同时更新,并且手机列表数组会被重新排序。这个时候数据绑定从另一个方向产生了作用——即数据从视图到模型的绑定。

测试

我们所做的更改可以通过一个单元测试或者一个端到端测试来验证正确性。我们首先来看看单元测试:

test/unit/controllersSpec.js:

describe('PhoneCat controllers', function() {

 describe('PhoneListCtrl', function(){
  var scope, ctrl;

  beforeEach(function() {
   scope = {},
   ctrl = new PhoneListCtrl(scope);
  });

  it('should create "phones" model with 3 phones', function() {
   expect(scope.phones.length).toBe(3);
  });

  it('should set the default value of orderProp model', function() {
   expect(scope.orderProp).toBe('age');
  });
 });
});

单元测试现在验证了默认值被正确设置。

我们使用Jasmine的接口把PhoneListCtrl控制器提取到一个beforeEach块中,这个块会被所有的父块describe中的所有测试所共享。

运行这些单元测试,跟以前一样,执行./scripts/test.sh脚本,你应该会看到如下输出(注意:要在浏览器打开http://localhost:9876并进入严格模式,测试才会运行!):

Chrome: Runner reset.
..
Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (3.00 ms)
 Chrome 19.0.1084.36 Mac OS: Run 2 tests (Passed: 2; Fails: 0; Errors 0) (3.00 ms)

现在我们把注意力转移到端到端测试上来。

test/e2e/scenarios.js:

...
  it('should be possible to control phone order via the drop down select box',
    function() {
   //let's narrow the dataset to make the test assertions shorter
   input('query').enter('tablet');

   expect(repeater('.phones li', 'Phone List').column('phone.name')).
     toEqual(["Motorola XOOM\u2122 with Wi-Fi",
          "MOTOROLA XOOM\u2122"]);

   select('orderProp').option('Alphabetical');

   expect(repeater('.phones li', 'Phone List').column('phone.name')).
     toEqual(["MOTOROLA XOOM\u2122",
          "Motorola XOOM\u2122 with Wi-Fi"]);
  });
...

端到端测试验证了选项框的排序机制是正确的。

你现在可以刷新你的浏览器,然后重新跑一遍端到端测试,或者你可以在AngularJS的服务器上运行一下。

练习

在PhoneListCtrl控制器中,把设置orderProp那条语句删掉,你会看到AngularJS会在下拉菜单中临时添加一个空白的选项,并且排序顺序是默认排序(即未排序)。

在index.html模板里面添加一个`{{orderProp}}绑定来实时显示它的值。

总结

现在你已经为你的应用提供了搜索功能,并且完整的进行了测试。步骤5我们将学习AngularJS的服务以及AngularJS如何使用依赖注入。

以上就是对AngularJS 双向绑定的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

Javascript 相关文章推荐
Javascript 判断函数类型完美解决方案
Sep 02 Javascript
基于jQuery替换table中的内容并显示进度条的代码
Aug 02 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
Mar 13 Javascript
jquery插件之文字间歇自动向上滚动效果代码
Feb 25 Javascript
jQuery中通过ajax的get()函数读取页面的方法
Feb 29 Javascript
Bootstrap每天必学之滚动监听
Mar 16 Javascript
js捕捉键盘事件和按键键值的方法
Oct 10 Javascript
JavaScript基于replace+正则实现ES6的字符串模版功能
Apr 25 Javascript
vue子父组件通信的实现代码
Jul 09 Javascript
node+multer实现图片上传的示例代码
Feb 18 Javascript
JS正则表达式验证密码强度
Mar 18 Javascript
React forwardRef的使用方法及注意点
Jun 13 Javascript
AngularJS入门教程之迭代器过滤详解
Aug 18 #Javascript
AngularJS入门教程之AngularJS 模板
Aug 18 #Javascript
AngularJS入门教程之静态模板详解
Aug 18 #Javascript
AngularJS入门教程引导程序
Aug 18 #Javascript
Bootstrap模态框(modal)垂直居中的实例代码
Aug 18 #Javascript
js 获取站点应用名的简单实例
Aug 18 #Javascript
BootStrap日期控件在模态框中选择时间下拉菜单无效的原因及解决办法(火狐下不能点击)
Aug 18 #Javascript
You might like
php fsockopen伪造post与get方法的详解
2013/06/14 PHP
Yii框架获取当前controlle和action对应id的方法
2014/12/03 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
深入讲解PHP的对象注入(Object Injection)
2017/03/01 PHP
php PDO实现的事务回滚示例
2017/03/23 PHP
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
某人初学javascript的时候写的学习笔记
2010/12/30 Javascript
JS判断浏览器是否支持某一个CSS3属性的方法
2014/10/17 Javascript
JQuery实现带排序功能的权限选择实例
2015/05/18 Javascript
javascript获取文档坐标和视口坐标
2015/05/26 Javascript
九种原生js动画效果
2015/11/11 Javascript
jQuery中cookie插件用法实例分析
2015/12/04 Javascript
jQuery入门之层次选择器实例简析
2015/12/11 Javascript
JavaScript实现图片自动加载的瀑布流效果
2016/04/11 Javascript
jQuery前端开发35个小技巧
2016/05/24 Javascript
javascript正则表达式之分组概念与用法实例
2016/06/16 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
2016/09/19 Javascript
js canvas仿支付宝芝麻信用分仪表盘
2016/11/16 Javascript
微信小程序开发之入门实例教程篇
2017/03/07 Javascript
一步步教你利用webpack如何搭一个vue脚手架(超详细讲解和注释)
2018/01/08 Javascript
Vue中&quot;This dependency was not found&quot;问题的解决方法
2018/06/19 Javascript
Node.js log4js日志管理详解
2018/07/31 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
让你30分钟快速掌握vue3教程
2020/10/26 Javascript
Python的函数嵌套的使用方法
2014/01/24 Python
详解Python字典小结
2018/10/20 Python
Python3实现爬取简书首页文章标题和文章链接的方法【测试可用】
2018/12/11 Python
pytorch 可视化feature map的示例代码
2019/08/20 Python
Python list与NumPy array 区分详解
2019/11/06 Python
YSL圣罗兰美妆官方旗舰店:购买YSL口红
2018/04/16 全球购物
法律专业个人实习自我鉴定
2013/09/23 职场文书
会计系个人求职信范文分享
2013/12/20 职场文书
2014厂务公开实施方案
2014/02/17 职场文书
2015年乡镇发展党员工作总结
2015/03/31 职场文书
苦儿流浪记读书笔记
2015/07/01 职场文书
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL