使用 Vue 计算属性

在这篇文章中,我们将添加一个计数器,使用 Vue 的计算属性来显示已完成的任务项数量。计算属性的工作原理类似于方法,但只有在它们的依赖项之一发生更改时才会重新运行。

先决条件

熟悉核心 HTMLCSSJavaScript 语言,了解 终端/命令行

Vue 组件以 JavaScript 对象的组合形式编写,这些对象管理应用程序的数据,以及基于 HTML 的模板语法,该语法映射到底层的 DOM 结构。对于安装,以及使用 Vue 的一些更高级的功能(如单文件组件或渲染函数),您需要一个安装了 node + npm 的终端。

目标 学习如何使用 Vue 计算属性。

使用计算属性

这里的目标是添加待办事项列表的摘要计数。这对用户来说可能很有用,同时也有助于为辅助技术标记列表。如果我们的待办事项列表中有 5 项,其中 2 项已完成,那么我们的摘要可以显示为“已完成 2 项,共 5 项”。虽然这样做可能很诱人

标记
<h2>
  {{ToDoItems.filter(item => item.done).length}} out of
  {{ToDoItems.length}} items completed
</h2>

它将在每次渲染时重新计算。对于像这样的小型应用程序,这可能无关紧要。对于大型应用程序,或者当表达式更复杂时,这可能会导致严重的性能问题。

更好的解决方案是使用 Vue 的 计算属性。计算属性的工作原理类似于方法,但只有在它们的依赖项之一发生更改时才会重新运行。在我们的例子中,只有在 ToDoItems 数组发生更改时才会重新运行。

要创建计算属性,我们需要在组件对象中添加一个 computed 属性,就像我们之前使用过的 methods 属性一样。

添加摘要计数器

methods 属性下方,将以下代码添加到您的 App 组件对象中。列表摘要方法将获取已完成的 ToDoItems 数量,并返回一个报告此数量的字符串。

js
computed: {
  listSummary() {
    const numberFinishedItems = this.ToDoItems.filter((item) =>item.done).length
    return `${numberFinishedItems} out of ${this.ToDoItems.length} items completed`
  }
}

现在,我们可以直接将 {{listSummary}} 添加到我们的模板中;我们将将其添加到一个 <h2> 元素中,位于我们的 <ul> 元素上方。我们还将添加一个 id 和一个 aria-labelledby 属性,将 <h2> 元素的内容指定为 <ul> 元素的标签。

按照描述添加 <h2> 元素,并更新您 App 模板中的 <ul> 元素,如下所示

标记
<h2 id="list-summary">{{listSummary}}</h2>
<ul aria-labelledby="list-summary" class="stack-large">
  <li v-for="item in ToDoItems" :key="item.id">
    <to-do-item
      :label="item.label"
      :done="item.done"
      :id="item.id"></to-do-item>
  </li>
</ul>

您现在应该在应用程序中看到列表摘要,并且当您添加更多待办事项时,总项数也会更新!但是,如果您尝试选中和取消选中一些项,您将发现一个错误。目前,我们实际上并没有跟踪“已完成”数据,因此已完成项的数量不会发生变化。

跟踪对“已完成”的更改

我们可以使用事件来捕获复选框更新并相应地管理我们的列表。

由于我们不是依赖于按钮按下触发更改,我们可以将 @change 事件处理程序附加到每个复选框,而不是使用 v-model

更新 ToDoItem.vue 中的 <input> 元素,使其看起来像这样。

标记
<input
  type="checkbox"
  class="checkbox"
  :id="id"
  :checked="isDone"
  @change="$emit('checkbox-changed')" />

由于我们只需要发出复选框已被选中,我们可以将 $emit() 内联包含。

App.vue 中,在 addToDo() 方法下方添加一个名为 updateDoneStatus() 的新方法。此方法应接受一个参数:待办事项 id。我们要找到具有匹配 id 的项,并将它的 done 状态更新为当前状态的反面

js
updateDoneStatus(toDoId) {
  const toDoToUpdate = this.ToDoItems.find((item) => item.id === toDoId)
  toDoToUpdate.done = !toDoToUpdate.done
}

我们希望在 ToDoItem 发出 checkbox-changed 事件时运行此方法,并将它的 item.id 作为参数传递。更新您的 <to-do-item></to-do-item> 调用,如下所示

标记
<to-do-item
  :label="item.label"
  :done="item.done"
  :id="item.id"
  @checkbox-changed="updateDoneStatus(item.id)">
</to-do-item>

现在,如果您选中 ToDoItem,您应该看到摘要相应地更新!

Our app, with a completed todo counter added. It currently reads 3 out of 5 items completed

总结

在这篇文章中,我们使用了计算属性,为我们的应用程序添加了一个不错的小功能。但是,我们还有更重要的事情要做——在下一篇文章中,我们将研究条件渲染,以及如何使用它在我们需要编辑现有待办事项时显示编辑表单。