Ember 互動性:頁尾功能、條件渲染
現在是時候開始處理我們應用程式中的頁尾功能了。在這裡,我們將使待辦事項計數器更新以顯示待完成的待辦事項的正確數量,並正確地將樣式應用於已完成的待辦事項(即已選中複選框的待辦事項)。我們還將連線我們的“清除已完成”按鈕。在此過程中,我們將學習如何在模板中使用條件渲染。
| 先決條件 |
至少,建議您熟悉核心 HTML、CSS 和 JavaScript 語言,並瞭解 終端/命令列。 更深入地瞭解現代 JavaScript 特性(如類、模組等)將非常有益,因為 Ember 大量使用它們。 |
|---|---|
| 目標 | 繼續學習關於元件類的知識,開始瞭解條件渲染,並連線一些頁尾功能。 |
連線頁尾的行為
要使頁尾正常工作,我們需要實現以下三個功能區域
- 待辦事項計數器。
- 所有、活動和已完成待辦事項的篩選器。
- 一個清除已完成待辦事項的按鈕。
- 因為我們需要從頁尾元件訪問我們的服務,所以我們需要為頁尾生成一個類。輸入以下終端命令來執行此操作bash
ember generate component-class footer - 接下來,找到新建立的
todomvc/app/components/footer.js檔案,並將其更新為以下內容jsimport Component from "@glimmer/component"; import { inject as service } from "@ember/service"; export default class FooterComponent extends Component { @service("todo-data") todos; } - 現在我們需要回到我們的
todo-data.js檔案中,並新增一些功能,使我們能夠返回未完成的待辦事項的數量(對於顯示剩餘數量很有用),並從列表中清除已完成的待辦事項(這就是“清除已完成”功能所需的功能)。在todo-data.js中,在現有的all()getter 下方新增以下 getter,以定義未完成的待辦事項實際上是什麼使用 Ember 的jsget incomplete() { return this.todos.filterBy('isCompleted', false); }ArrayProxy.filterBy()方法,我們可以根據簡單的相等條件輕鬆地過濾陣列中的物件。在這裡,我們要求所有isCompleted屬性等於false的待辦事項,並且因為isCompleted在我們的Todo物件中是@tracked的,所以這個 getter 會在陣列中物件的值發生變化時重新計算。 - 接下來,在現有的
add(text)動作下方新增以下動作這對於清除待辦事項非常不錯——我們只需要將js@action clearCompleted() { this.todos = this.incomplete; }todos陣列設定為等於未完成待辦事項的列表。 - 最後,我們需要在我們的
footer.hbs模板中使用這個新功能。現在轉到這個檔案。 - 首先,替換這行用這個,它使用hbs
<strong>0</strong> todos leftincomplete陣列的長度填充未完成的數量hbs<strong>{{this.todos.incomplete.length}}</strong> todos left - 接下來,替換這個用這個hbs
<button type="button" class="clear-completed">hbs<button type="button" class="clear-completed" {{on 'click' this.todos.clearCompleted}}>
因此,現在當單擊按鈕時,我們之前新增的 clearCompleted() 動作將執行。但是,如果您嘗試單擊“清除已完成”按鈕,它似乎不會做任何事情,因為目前還沒有辦法“完成”待辦事項。我們需要將 todo.hbs 模板連線到服務,以便選中相關複選框會更改每個待辦事項的狀態。我們將在下一步中執行此操作。
待辦事項/待辦事項複數問題
以上內容很好,但我們還有另一個需要解決的小問題。即使只有一個待辦事項剩下,"剩餘待辦事項"指示器也總是顯示“x 個待辦事項剩下”,這語法錯誤!
要解決此問題,我們需要更新模板的這部分以包含一些條件渲染。在 Ember 中,您可以使用 條件內容 條件地渲染模板的某些部分;一個簡單的塊示例如下所示
{{#if this.thingIsTrue}} Content for the block form of "if"
{{/if}}
所以讓我們嘗試替換 footer.hbs 的這部分
<strong>{{this.todos.incomplete.length}}</strong> todos left
用以下內容
<strong>{{this.todos.incomplete.length}}</strong>
{{#if this.todos.incomplete.length === 1}} todo
{{else}} todos
{{/if}} left
但是這會給我們一個錯誤——在 Ember 中,這些簡單的 if 語句目前只能測試真值/假值,而不是更復雜的表示式,例如比較。要解決此問題,我們必須在 todo-data.js 中新增一個 getter 以返回 this.incomplete.length === 1 的結果,然後在我們的模板中呼叫它。
在現有的 getter 下方將以下新 getter 新增到 todo-data.js。請注意,這裡我們需要 this.incomplete.length,而不是 this.todos.incomplete.length,因為我們在服務內部進行此操作,在那裡 incomplete() getter 可直接使用(在模板中,服務的內容透過 footer 類中的 @service('todo-data') todos; 行在 todos 中可用,因此在那裡它是 this.todos.incomplete.length)。
get todoCountIsOne() {
return this.incomplete.length === 1;
}
然後回到 footer.hbs,並將我們之前編輯的模板部分更新為以下內容
<strong>{{this.todos.incomplete.length}}</strong>
{{#if this.todos.todoCountIsOne}}todo{{else}}todos{{/if}} left
現在儲存並測試,您將看到當您只有一個待辦事項時會使用正確的複數形式!
請注意,這是 Ember 中 if 的塊形式;您也可以使用內聯形式
{{if this.todos.todoCountIsOne "todo" "todos"}}
完成待辦事項
與其他元件一樣,我們需要一個類來訪問服務。
建立待辦事項類
- 在您的終端中執行以下命令bash
ember generate component-class todo - 現在轉到新建立的
todomvc/app/components/todo.js檔案,並將內容更新為如下所示,以便待辦事項元件可以訪問服務jsimport Component from "@glimmer/component"; import { inject as service } from "@ember/service"; export default class TodoComponent extends Component { @service("todo-data") todos; } - 接下來,再次回到我們的
todo-data.js服務檔案,並在之前動作下方新增以下動作,這將使我們能夠切換每個待辦事項的完成狀態js@action toggleCompletion(todo) { todo.isCompleted = !todo.isCompleted; }
更新模板以顯示已完成狀態
最後,我們將編輯 todo.hbs 模板,以便複選框的值現在繫結到待辦事項上的 isCompleted 屬性,並且當發生更改時,會呼叫待辦事項服務上的 toggleCompletion() 方法。
- 在
todo.hbs中,首先找到以下行並用這個替換它——您會注意到,這裡我們使用了一些條件內容來新增適當的類值hbs<li>hbs<li class={{ if @todo.isCompleted 'completed' }}> - 接下來,找到以下行並用這個替換它hbs
<input aria-label="Toggle the completion of this todo" class="toggle" type="checkbox" >hbs<input class="toggle" type="checkbox" aria-label="Toggle the completion of this todo" checked={{ @todo.isCompleted }} {{ on 'change' (fn this.todos.toggleCompletion @todo) }} >
嘗試重新啟動開發伺服器並再次轉到 localhost:4200,您現在將看到我們有一個完全可操作的“剩餘待辦事項”計數器和清除按鈕
如果您想知道為什麼我們沒有直接在元件上進行切換(因為該函式完全自包含,並且不需要來自服務中的任何內容),那麼您問這個問題完全正確!但是,因為我們最終會希望將所有待辦事項列表的更改持久化或同步到 本地儲存(參見 應用程式的最終版本),將所有更改持久化狀態的操作放在同一個地方是有意義的。