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编程起步(第一课)
Jan 10 Javascript
[原创]后缀就扩展名为js的文件是什么文件
Dec 06 Javascript
AngularJS实现表单验证
Jan 28 Javascript
innerHTML属性,outerHTML属性,textContent属性,innerText属性区别详解
Mar 13 Javascript
jQuery Validate表单验证深入学习
Dec 18 Javascript
jQuery删除节点用法示例(remove方法)
Sep 08 Javascript
jQuery实现对象转为url参数的方法
Jan 11 Javascript
iscroll-probe实现下拉刷新和下拉加载效果
Jun 28 Javascript
VUE 实现动态给对象增加属性,并触发视图更新操作示例
Nov 29 Javascript
JavaScript检测浏览器是否支持CSS变量代码实例
Apr 03 Javascript
基于VUE实现简单的学生信息管理系统
Jan 13 Vue.js
vue-cli3.x配置全局的scss的时候报错问题及解决
Apr 30 Vue.js
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
PHP5下$_SERVER变量不再受magic_quotes_gpc保护的弥补方法
2012/10/31 PHP
PHP中使用file_get_contents post数据代码例子
2015/02/13 PHP
php处理复杂xml数据示例
2016/07/11 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
js实现GridView单选效果自动设置交替行、选中行、鼠标移动行背景色
2010/05/27 Javascript
JS操作图片(增,删,改) 例子
2013/04/17 Javascript
JS中的forEach、$.each、map方法推荐
2016/04/05 Javascript
node.js 动态执行脚本
2016/06/02 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
2016/08/25 Javascript
Bootstrap弹出框modal上层的输入框不能获得焦点问题的解决方法
2016/12/13 Javascript
vue使用vue-cli快速创建工程
2017/07/28 Javascript
vue按需引入element Transfer 穿梭框
2017/09/30 Javascript
写一个移动端惯性滑动&amp;回弹Vue导航栏组件 ly-tab
2018/03/06 Javascript
angular 组件通信的几种实现方式
2018/07/13 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
[02:23]2018DOTA2亚洲邀请赛趣味视频——反应测试
2018/04/04 DOTA
[58:32]EG vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python遍历一个目录,输出所有的文件名的实例
2018/04/23 Python
Python实现的企业粉丝抽奖功能示例
2019/07/26 Python
自适应线性神经网络Adaline的python实现详解
2019/09/30 Python
Python Flask框架实现简单加法工具过程解析
2020/06/03 Python
python实现每天自动签到领积分的示例代码
2020/08/18 Python
python复合条件下的字典排序
2020/12/18 Python
python opencv肤色检测的实现示例
2020/12/21 Python
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
联想法国官方网站:Lenovo法国
2018/10/18 全球购物
params有什么用
2016/03/01 面试题
幼儿园教师培训制度
2014/01/16 职场文书
商学院大学生求职的自我评价
2014/03/12 职场文书
《果园机器人》教学反思
2014/04/13 职场文书
创意婚礼策划方案
2014/05/18 职场文书
个人授权委托书范文
2014/09/21 职场文书
新郎结婚感言
2015/07/31 职场文书
如何让2019年上半年的工作总结更出色!
2019/07/01 职场文书
CSS filter 有什么神奇用途
2021/05/25 HTML / CSS