美文网首页一起学AngularJS
【一起学AngularJS】第六章、双向数据绑定

【一起学AngularJS】第六章、双向数据绑定

作者: 40ab6525bf35 | 来源:发表于2016-03-10 14:37 被阅读127次

    本章节中,我们将为之前展示的手机信息列表提供一个排序功能。要想实现动态排序的功能,我们只需要新建一个模型属性,并且把它和循环器绑定在一起,剩下的就交给数据绑定去完成了。
    相比上一章中的例子,本章中的例子多添加了一个下拉菜单,它允许用户自己控制手机列表的显示顺序。首先我们把代码切换到step-4:

    git checkout -f step-4
    

    刷新浏览器查看效果(假设之前你已经运行了上一章的例子)。你可以在线看效果

    模版

    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">
        <span>{{phone.name}}</span>
        <p>{{phone.snippet}}</p>
      </li>
    </ul>
    

    代码对index.html主要做了以下几点改动:

    • 第一布我们添加一个名为orderProp<select>标签元素,这样用户就能从提供的两种排序中选择自己想要的排序方式了。
    • 第二步我们再之前的filter过滤器链中添加一个orderBy过滤器用来对结果进行排序。orderBy过滤器的输入为一个数组,对其进行排序并且返回排序后的数组。

    这个例子中,Angular在<select>元素和orderProp数据模型之间建立双向数据绑定,然后orderBy过滤器就可以用它作为输入,并且返回结果了。
    上一章中我们讨论了关于循环器的数据绑定,只要模型数据发生变化(比如用户下拉排序菜单选择了不通的排序方式),Angular的数据绑定功能将确保页面会同步展示最新结果。其他的手工控制代码都不用自己写。

    控制器

    app/js/controllers.js:

    var phonecatApp = angular.module('phonecatApp', []);
    
    phonecatApp.controller('PhoneListCtrl', function ($scope) {
      $scope.phones = [
        {'name': 'Nexus S',
         'snippet': 'Fast just got faster with Nexus S.',
         'age': 1},
        {'name': 'Motorola XOOM? with Wi-Fi',
         'snippet': 'The Next, Next Generation tablet.',
         'age': 2},
        {'name': 'MOTOROLA XOOM?',
         'snippet': 'The Next, Next Generation tablet.',
         'age': 3}
      ];
    
      $scope.orderProp = 'age';
    });
    

    上述代码主要包含以下改动:

    • 首先我们修改了phones数据模型,为每条手机记录添加了一个age属性。页面将支持根据这个属性来排序。
    • 另外我们在接下来的一行中把orderProp的默认值设成age(告诉页面第一次载入时按照age排序)。如果这里没有设置默认值,页面在载入的时候将是未排序过的,直到用户从下拉菜单中选择了一个排序方式。

    这个例子能非常好的说明双向绑定这个概念。当页面载入后,我们可以看到下拉框显示的是"Newest",这是因为我们把orderProp默认设置为了age。这是一次从数据模型到UI的单向绑定。另外一方面,当我们选择下拉菜单的"Alphabetical",后台中的手机数组列表就会被重新排列,这就是从UI到数据模型的单向绑定。这两者结合起来,就是数据的双向绑定了。

    测试

    这次的改动将涉及单元测试和E2E测试两个测试。我们先看以下单元测试:
    test/unit/controllersSpec.js:

    describe('PhoneCat controllers', function() {
    
      describe('PhoneListCtrl', function(){
        var scope, ctrl;
    
        beforeEach(module('phonecatApp'));
    
        beforeEach(inject(function($controller) {
          scope = {};
          ctrl = $controller('PhoneListCtrl', {$scope: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');
        });
      });
    });
    

    上述单元测试代码将验证orderProp默认值是否设置成功。
    我们使用了Jasmine的API来把控制器的构造过程抽取出来放入了beforeEach模块中,这将使得它能被父模块describe中的所有测试所共享。
    你将会从Karma的控制台输出中看到以下消息:

    Chrome 22.0: Executed 2 of 2 SUCCESS (0.021 secs / 0.001 secs)
    

    下面让我们来看看E2E测试,以下是代码:
    test/e2e/scenarios.js:

    ...
    it('should be possible to control phone order via the drop down select box', function() {
    
      var phoneNameColumn = element.all(by.repeater('phone in phones').column('phone.name'));
      var query = element(by.model('query'));
    
      function getNames() {
        return phoneNameColumn.map(function(elm) {
          return elm.getText();
        });
      }
    
      query.sendKeys('tablet'); //let's narrow the dataset to make the test assertions shorter
    
      expect(getNames()).toEqual([
        "Motorola XOOM\u2122 with Wi-Fi",
        "MOTOROLA XOOM\u2122"
      ]);
    
      element(by.model('orderProp')).element(by.css('option[value="name"]')).click();
    
      expect(getNames()).toEqual([
        "MOTOROLA XOOM\u2122",
        "Motorola XOOM\u2122 with Wi-Fi"
      ]);
    });...
    

    E2E测试将用来验证下拉选择框的排序功能是否正常。你可以通过npm run protractor来运行这个测试用例。

    实验小能手

    1. PhoneListCtrl控制器代码中,把$scope.orderProp = 'age';这句话注释掉,然后你就会看到Angular会为页面上的下拉框添加了一个新的空白选项(Unknown),并且当前的列表也是未经排序的。
    2. 添加一个{{orderProp}}数据绑定用来查看当前的排序方式。
    3. 想要倒排某个排序?很简单,尝试添加一个新的select选项:<option value="-age">Oldest</option>

    总结

    现在我们已经为网站添加了排序功能,下一章,我们将学习Angular的服务体系和依赖注入。

    相关文章

      网友评论

        本文标题:【一起学AngularJS】第六章、双向数据绑定

        本文链接:https://www.haomeiwen.com/subject/hqytlttx.html