AngularJS入门教程之迭代器过滤详解


Posted in Javascript onAugust 18, 2016

我们在上一步做了很多基础性的训练,所以现在我们可以来做一些简单的事情喽。我们要加入全文检索功能(没错,这个真的非常简单!)。同时,我们也会写一个端到端测试,因为一个好的端到端测试可以帮上很大忙。它监视着你的应用,并且在发生回归的时候迅速报告。

请重置工作目录:

git checkout -f step-3

我们的应用现在有了一个搜索框。注意到页面上的手机列表随着用户在搜索框中的输入而变化。

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

控制器

我们对控制器不做任何修改。

模板

app/index.html

<div class="container-fluid">
 <div class="row-fluid">
  <div class="span2">
   <!--Sidebar content-->

   Search: <input ng-model="query">

  </div>
  <div class="span10">
   <!--Body content-->

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

    </div>
 </div>
</div>

我们现在添加了一个<input>标签,并且使用AngularJS的$filter函数来处理ngRepeat指令的输入。

这样允许用户输入一个搜索条件,立刻就能看到对电话列表的搜索结果。我们来解释一下新的代码:

数据绑定: 这是AngularJS的一个核心特性。当页面加载的时候,AngularJS会根据输入框的属性值名字,将其与数据模型中相同名字的变量绑定在一起,以确保两者的同步性。

在这段代码中,用户在输入框中输入的数据名字称作query,会立刻作为列表迭代器(phone in phones | filter:query`)其过滤器的输入。当数据模型引起迭代器输入变化的时候,迭代器可以高效得更新DOM将数据模型最新的状态反映出来。

AngularJS入门教程之迭代器过滤详解

使用filter过滤器:filter函数使用query的值来创建一个只包含匹配query记录的新数组。

ngRepeat会根据filter过滤器生成的手机记录数据数组来自动更新视图。整个过程对于开发者来说都是透明的。

测试

在步骤2,我们学习了编写和运行一个测试的方法。单元测试用来测试我们用js编写的控制器和其他组件都非常方便,但是不能方便的对DOM操作和应用集成进行测试。对于这些来说,端到端测试是一个更好的选择。

搜索特性是完全通过模板和数据绑定实现的,所以我们的第一个端到端测试就来验证这些特性是否符合我们的预期。

test/e2e/scenarios.js:

describe('PhoneCat App', function() {

 describe('Phone list view', function() {

  beforeEach(function() {
   browser().navigateTo('../../app/index.html');
  });


  it('should filter the phone list as user types into the search box', function() {
   expect(repeater('.phones li').count()).toBe(3);

   input('query').enter('nexus');
   expect(repeater('.phones li').count()).toBe(1);

   input('query').enter('motorola');
   expect(repeater('.phones li').count()).toBe(2);
  });
 });
});

尽管这段测试代码的语法看起来和我们之前用Jasmine写的单元测试非常像,但是端到端测试使用的是AngularJS端到端测试器提供的接口。

运行一个端到端测试,在浏览器新标签页中打开下面任意一个:

node.js用户:http://localhost:8000/test/e2e/runner.html

使用其他http服务器的用户:http://localhost:[port-number]/[context-path]/test/e2e/runner.html

访客:http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html

这个测试验证了搜素框和迭代器被正确地集成起来。你可以发现,在AngularJS里写一个端到端测试多么的简单。尽管这个例子仅仅是一个简单的测试,但是用它来构建任何一个复杂、可读的端到端测试都很容易。

练习

在index.html模板中添加一个{{query}}绑定来实时显示query模型的当前值,然后观察他们是如何根据输入框中的值而变化。
现在我们来看一下我们怎么让query模型的值出现在HTML的页面标题上。

你或许认为像下面这样在title标签上加上一个绑定就行了:

<title>Google Phone Gallery: {{query}}</title>

但是,当你重载页面的时候,你根本没办法得到期望的结果。这是因为query模型仅仅在body元素定义的作用域内才有效。

<body ng-controller="PhoneListCtrl">

如果你想让<title>元素绑定上query模型,你必须把ngController声明移动到HTML元素上,因为它是title和body元素的共同祖先。

<html ng-app ng-controller="PhoneListCtrl">

一定要注意把body元素上的ng-controller声明给删了。

当绑定两个花括号在title元素上可以实现我们的目标,但是你或许发现了,页面正加载的时候它们已经显示给用户看了。一个更好的解决方案是使用ngBind或者ngBindTemplate指令,它们在页面加载时对用户是不可见的:

<title ng-bind-template="Google Phone Gallery: {{query}}">Google Phone Gallery</title>

在test/e2e/scenarios.js的describe块中加入下面这些端到端测试代码:

it('should display the current filter value within an element with id "status"',
  function() {
    expect(element('#status').text()).toMatch(/Current filter: \s*$/);
    input('query').enter('nexus');
    expect(element('#status').text()).toMatch(/Current filter: nexus\s*$/);
    //alternative version of the last assertion that tests just the value of the binding
    using('#status').expect(binding('query')).toBe('nexus');
});

刷新浏览器,端到端测试器会报告测试失败。为了让测试通过,编辑index.html,添加一个id为“status”的div或者p元素,内容是一个query绑定,再加上Current filter:前缀。例如:

<div id="status">Current filter: {{query}}</div>

在端到端测试里面加一条pause();语句,重新跑一遍。你将发现测试器暂停了!这样允许你有机会在测试运行过程中查看你应用的状态。测试应用是实时的!你可以更换搜索内容来证明。稍有经验你就会知道,这对于在端到端测试中迅速找到问题是多么的关键。

总结

我们现在添加了全文搜索功能,并且完成一个测试证明了搜索是对的!现在让我们继续到步骤4来看看给我们的手机应用增加排序功能。

以上就是对AngularJS 迭代器过滤资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

Javascript 相关文章推荐
Js nodeType 属性全面解析
Nov 14 Javascript
js格式化时间小结
Nov 03 Javascript
Vue.js基础知识汇总
Apr 27 Javascript
js自定义select下拉框美化特效
May 12 Javascript
angularjs项目的页面跳转如何实现(5种方法)
May 25 Javascript
vue mint-ui 实现省市区街道4级联动示例(仿淘宝京东收货地址4级联动)
Oct 16 Javascript
在Vue组件中使用 TypeScript的方法
Feb 28 Javascript
vue-cli3脚手架的配置及使用教程
Aug 28 Javascript
详解React项目中碰到的IE问题
Mar 14 Javascript
React传值 组件传值 之间的关系详解
Aug 26 Javascript
Javascript之datagrid查询详解
Sep 15 Javascript
JS前端可视化canvas动画原理及其推导实现
Aug 05 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
js修改onclick动作的四种方法(推荐)
Aug 18 #Javascript
You might like
mac下使用brew配置环境的步骤分享
2011/05/23 PHP
php入门学习知识点一 PHP与MYSql连接与查询
2011/07/14 PHP
PHP cURL获取微信公众号access_token的实例
2018/04/28 PHP
Laravel框架在本地虚拟机快速安装的方法详解
2018/06/11 PHP
用js做一个小游戏平台 (一)
2009/12/29 Javascript
Javascript 学习笔记之 对象篇(二) : 原型对象
2014/06/24 Javascript
JavaScript中的6种运算符总结
2014/10/16 Javascript
通过Tabs方法基于easyUI+bootstrap制作工作站
2016/03/28 Javascript
AngularJs bootstrap搭载前台框架——js控制部分
2016/09/01 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
js闭包用法实例详解
2016/12/13 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
2017/01/20 Javascript
js指定步长实现单方向匀速运动
2017/07/17 Javascript
express框架实现基于Websocket建立的简易聊天室
2017/08/10 Javascript
10个最优秀的Node.js MVC框架
2017/08/24 Javascript
详解小程序原生使用ES7 async/await语法
2018/08/06 Javascript
JS判断用户用的哪个浏览器实例详解
2018/10/09 Javascript
vue中重定向redirect:‘/index‘,不显示问题、跳转出错的完美解决
2020/09/28 Javascript
[56:12]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第一场 6.3
2018/06/04 DOTA
CentOS中使用virtualenv搭建python3环境
2015/06/08 Python
python中类的属性和方法介绍
2018/11/27 Python
详解从Django Rest Framework响应中删除空字段
2019/01/11 Python
Python解析多帧dicom数据详解
2020/01/13 Python
解决python父线程关闭后子线程不关闭问题
2020/04/25 Python
马云的职业生涯规划之路
2014/01/01 职场文书
幼儿园门卫岗位职责
2014/02/14 职场文书
任命书怎么写
2014/06/04 职场文书
经济国贸专业求职信
2014/06/18 职场文书
工资收入证明
2014/10/07 职场文书
志愿者个人总结
2015/03/03 职场文书
2015年高校就业工作总结
2015/05/04 职场文书
运动会观后感
2015/06/09 职场文书
诚信考试主题班会
2015/08/17 职场文书
承诺书的内容有哪些,怎么写?
2019/06/21 职场文书
matplotlib之pyplot模块实现添加子图subplot的使用
2021/04/25 Python
html原生table实现合并单元格以及合并表头的示例代码
2023/05/07 HTML / CSS