AngularJS 篩選迭代器

2022-04-15 14:32 更新

篩選迭代器

我們在上一步中為開發(fā)應(yīng)用打基礎(chǔ)做了很多工作,現(xiàn)在我們將做一些簡單的事情;我們將添加全文搜索(是的,它很簡單?。N覀冞€將編寫一個端到端測試,因為一個好的端到端測試可以幫上大忙。它監(jiān)視著你的應(yīng)用,并在發(fā)生回歸時迅速報告。

  • 現(xiàn)在應(yīng)用有了一個搜索框。注意頁面上的手機列表的變化取決于用戶在搜索框中打了什么字。

把工作空間重置到第三步

git checkout -f step-3

刷新你的瀏覽器或在線檢查這一步:Step 3 Live Demo

下面列出了第二步和第三步之間最重要的區(qū)別。你可以在GitHub里看到完整的差異。

控制器

我們對控制器不作修改。

模板

app/index.html:

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-2">
        <!--Sidebar content-->

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

      </div>
      <div class="col-md-10">
        <!--Body content-->

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

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

我們添加了一個標(biāo)準(zhǔn)HTML<input>元素標(biāo)記,并使用Angular的filter函數(shù)來處理repeat指令的輸入。

這使用戶輸入搜索條件,并在手機列表中快速看到搜索結(jié)果。新的代碼演示如下:

  • 數(shù)據(jù)綁定:這是Angular的一個核心功能。當(dāng)網(wǎng)頁載入時,Angular把輸入框的名稱綁定到數(shù)據(jù)模塊的同名的變量上,并保持兩者同步。

    在代碼中,用戶打字到輸入框的數(shù)據(jù)(命名為query)很快可以作為一個篩選器輸入到列表迭代器(phone in phones | filter:query)中。在改變數(shù)據(jù)模塊的時候,導(dǎo)致迭代器的輸入發(fā)生變化,迭代器有效地更新了DOM,以反映模塊的當(dāng)前狀態(tài)。

  • 使用filter篩選器:filter函數(shù)使用了query值發(fā)創(chuàng)建一個新的數(shù)列,只包含匹配query的記錄。

    ngRepeat自動更新了視力,以響應(yīng)filter篩選器返回的手機數(shù)字的變化。該處理對開發(fā)者來說是完全透明的。

測試

在第二步中,我們學(xué)會了如何編寫并運行單元測試。對于測試我們的用JavaScript編寫的應(yīng)用程序的控制器和其它組件,單元測試是完美的,但是測試DOM操作或測試我們的應(yīng)用程序的接通不太方便。針對這些,一個端到端的測試是一個更好的選擇。

該搜索功能完全是通過模板和數(shù)據(jù)綁定來實現(xiàn)的,我們將編寫我們第一個端到端的測試,以驗證該功能起了什么作用。

test/e2e/scenarios.js:

describe('PhoneCat App', function() {

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

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

    it('should filter the phone list as a user types into the search box', function() {

      var phoneList = element.all(by.repeater('phone in phones'));
      var query = element(by.model('query'));

      expect(phoneList.count()).toBe(3);

      query.sendKeys('nexus');
      expect(phoneList.count()).toBe(1);

      query.clear();
      query.sendKeys('motorola');
      expect(phoneList.count()).toBe(2);
    });
  });
});

這個測試驗證了搜索框以及迭代器是否正確地接通了。注意,在Angular中,編寫端到端測試是如此地容易。雖然這個示例只針對一個簡單的測試,但是它確實很容易測試任何功能化的、可讀的、端到端的測試。

利用Protractor運行端到端的測試

甚至雖然測試的句法看起來很像我們的用Jasmine編寫的控制器單元測試,但是端到端測試使用Protractor的API。在http://angular.github.io/protractor/#/api可以讀到Protractor的API。

與Karma很像的是針對單元測試的測試運行者,我們使用Protractor以運行端到端測試。用npm run protractor來嘗試它。端到端測試很慢,所以與單元測試不同,在運行測試之后Protractor將退出,不會自動在每次文件更改時重新運行測試套裝。要想重新運行測試套裝,需要再次執(zhí)行npm run protractor

注意,你必須確保你的應(yīng)用通過一個web服務(wù)器提供服務(wù),從而用Protractor測試。你可以使用`npm start`來做到這。你還需要確保你在運行`npm run protractor`之前已經(jīng)安裝了Protractor,并更新了web驅(qū)動器。You can do this by issuing `npm install` and `npm run update-webdriver` into your terminal.

實驗

顯示當(dāng)前查詢

通過添加一個綁定到index.html模板的{{query}}來顯示query模塊當(dāng)前的值,并看到當(dāng)你在輸入框中打字時,它如何變化。

在標(biāo)題中顯示查詢

讓我們看到我們可以取得query模板的當(dāng)前值,模塊出現(xiàn)在HTML網(wǎng)頁的標(biāo)題上。

  • 把一個端到端測試添加到describe塊中,test/e2e/scenarios.js看起來將如這:

      describe('PhoneCat App', function() {
    
        describe('Phone list view', function() {
    
          beforeEach(function() {
            browser.get('app/index.html');
          });
    
          var phoneList = element.all(by.repeater('phone in phones'));
          var query = element(by.model('query'));
    
          it('should filter the phone list as a user types into the search box', function() {
            expect(phoneList.count()).toBe(3);
    
            query.sendKeys('nexus');
            expect(phoneList.count()).toBe(1);
    
            query.clear();
            query.sendKeys('motorola');
            expect(phoneList.count()).toBe(2);
          });
    
          it('should display the current filter value in the title bar', function() {
            query.clear();
            expect(browser.getTitle()).toMatch(/Google Phone Gallery:\s*$/);
    
            query.sendKeys('nexus');
            expect(browser.getTitle()).toMatch(/Google Phone Gallery: nexus$/);
          });
        });
      });

    運行protractor(npm run protractor),看到測試失敗了。

  • 你可能認(rèn)為你只需要用以下方式向標(biāo)題標(biāo)簽添加{{query}}

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

    然而,當(dāng)你重載入這個網(wǎng)頁的時候,你不會看到想要的結(jié)果。這是因為“查詢”模塊駐留在作用域內(nèi),由ng-controller="PhoneListCtrl"指令在body元素上定義。

    <body ng-controller="PhoneListCtrl">

    如果你想要從<title>元素上綁定查詢模塊,你必須把ngController聲明移動到HTML元素上,因為它是body元素和title元素常用的父元素。

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

    確保從body元素中移除ng-controller聲明。

  • 重新運行rpm run protractor,看到現(xiàn)在測試已經(jīng)看通過了。

  • 在title元素內(nèi)部使用雙花工作得很好,與此同時,你可能會注意到頁面加載的一瞬間它們確實顯示給用戶了。一個更好的解決方案是使用ngBind指令ngBindTemplate指令,當(dāng)頁面加載時用戶能看到它們。

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

總結(jié)

我們現(xiàn)在已經(jīng)把全文搜索添加上去了,還包含了一個用來驗證搜索是否起作用的測試!現(xiàn)在讓我們前往第四步 雙路數(shù)據(jù)綁定以學(xué)會如何向手機應(yīng)用添加排序功能。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號