V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
powertoolsteam
V2EX  ›  推广

Vue 中的计算属性、方法和侦听属性的区别

  •  
  •   powertoolsteam · 2019-09-25 14:25:40 +08:00 · 1560 次点击
    这是一个创建于 1889 天前的主题,其中的信息可能已经有所发展或是发生改变。

    对于刚开始学习 Vue 的开发者来说,十分容易混淆 Vue 中计算属性、方法和侦听属性,希望通过本文的介绍,您能了解并分辨这三者的区别。

    熟悉 Vue 的同学都知道:在 Vue 框架中,计算属性( computed )、方法( methods )和侦听属性( watchers )充当着非常重要的角色,它们既可以用来实现相同的功能,彼此之间又存在一些不同之处。三者都有适合自己的场景,我们要想在合适的场景下灵活运用它们,必须对它们有全面的了解。

    方法( methods )

    正如他的名字一样,它们是挂载在对象上的函数,通常是 Vue 实例本身或 Vue 组件。

    您可以使用 methods 对 DOM 中发生的事件做出反应,也可以从组件中的其他位置调用它们,例如,从计算属性( computed )或侦听( watchers )中调用。

    Methods 主要用于对常用功能进行分组,包括处理表单提交,以及构建可重用功能时,例如发出 Ajax 请求。

    在 methods 对象内部的 Vue 实例中创建方法如下:

    new Vue({
      el: "#app",
      methods: {
        handleSubmit() {}
      }
    })
    

    当需要在模板中使用 methods 时:

    <div id="app">
      <button @click="handleSubmit">
        Submit
      </button>
    </div>
    

    我们使用 v-on 指令将事件处理程序附加到我们的 DOM 元素,DOM 元素也可以缩写为 @符号。 以代码中的 handleSubmit 事件为例,每次单击按钮时都会调用该方法。 对于要传递方法体中需要的参数化的实例,可以执行以下操作:

    <button @click="handleSubmit(event)"> Submit </button>

    这里我们传递一个事件对象,例如,它允许我们在表单提交的情况下阻止浏览器的默认操作。

    但是,当我们使用指令来附加事件时,我们可以使用修饰符来更优雅地实现相同的操作: @click.stop="handleSubmit"

    现在让我们看一个使用 methods 过滤数组中数据列表的示例。

    在代码示例中,我们想要渲染数据列表和搜索框。每当用户在搜索框中输入值时,呈现的数据都会发生变化。模板看起来像这样:

    Language Search

    <input type="text" v-model="input" @keyup="handleSearch" placeholder="Enter language" class="form-control" />

      <ul v-for="(item, index) in languages" class="list-group">
        <li class="list-group-item" :key="item">{{ item }}</li>
      </ul>
    </div>
    

    我们引用了一个 handleSearch 方法,当用户在搜索字段中输入内容时都会调用该方法。我们需要创建 methods 和数据:

    new Vue({
      el: '#app',
      data() {
        return {
          input: '',
          languages: []
        }
      },
      methods: {
        handleSearch() {
          this.languages = [
            'JavaScript',
            'Ruby',
            'Scala',
            'Python',
            'Java',
            'Kotlin',
            'Elixir'
    
          ].filter(item => item.toLowerCase().includes(this.input.toLowerCase()))
        }
      },
      created() { this.handleSearch() }
    })
    

    该 handleSearch 方法使用输入字段的值来更新列出的项目。需要注意的是,在 methods 对象中,不需要引用该方法(正如您在 React 中所做的那样):this.handleSearch

    计算属性( Computed )

    计算属性看起来像一个方法,但事实却不同。在 Vue 中,我们使用 data 来跟踪对特定属性的更改,得到一定的反应。计算属性允许我们定义一个与数据使用相同方式的属性,但也可以有一些基于其依赖关系的自定义逻辑。

    虽然上面示例中的“搜索”代码会正常运行,但更优雅的解决方案是使用计算属性。计算属性对于从现有数据源提取组合新数据时非常方便,它们对 methods 的一大优势是:输出将被缓存。这也意味着如果页面上独立于计算属性的某些内容发生更改并且重新绘制 UI 时,将返回缓存的结果,并不会重新计算 Computed,这样做将大大简化计算步骤,提升处理性能。

    计算属性使我们能够使用可用的数据动态进行计算。假设我们有一个性能开销较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算,并且我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter !

    如下,模板看起来几乎与 methods 中相同,不同点是我们将指令传递给一个计算属性():v-forfilteredList

    Language Search

      <div class="form-group">
        <input
          type="text"
          v-model="input"
          placeholder="Enter language"
          class="form-control"
        />
      </div>
    
      <ul v-for="(item, index) in filteredList" class="list-group">
        <li class="list-group-item" :key="item">{{ item }}</li>
      </ul>
    </div>
    

    在脚本中,我们声明 data 属性中的语言(以前这是一个空数组),而不是一个方法,我们将我们的逻辑移动到一个计算属性: new Vue({ el: "#app", data() { return { input: '', languages: [ "JavaScript", "Ruby", "Scala", "Python", "Java", "Kotlin", "Elixir" ] } }, computed: { filteredList() { return this.languages.filter((item) => { return item.toLowerCase().includes(this.input.toLowerCase()) }) } } }) 该 filteredList 计算的属性将包含输入字段值项的数组。在第一次渲染时(当输入字段为空时),将渲染整个数组。当用户在字段中输入值时,filteredList 将返回一个包含在字段中输入的值的数组。

    使用计算属性时,您要计算的数据必须可用,否则会导致应用程序出错。 计算属性创建了一个新 filteredList 属性,这就是我们可以在模板中引用它的原因。filteredList 每次依赖关系时的更改值。这里容易发生变化的依赖是值的 input。

    最后,请注意计算属性允许我们创建一个变量以在我们的模板中使用,该模板是从一个或多个数据属性构建的。

    举例:从用户的名字和姓氏生成 fullName:

    computed: {
      fullName() {
        return `${this.firstName} ${this.lastName}`
      }
    }
    

    在下面的场景,但不限于以下场景中,都可以使用 Vue 的计算属性:

    • 在用户输入时更新大量信息,比如列表的过滤
    • 从 Vuex Store 中收集相关信息
    • 表单验证
    • 数据可视化的变化取决于用户需要看到什么

    侦听属性( watchers )

    当一些数据属性发生变化时,我们往往需要执行一些侦听手段,它可以帮助我们监听属性的变化,以便执行对应的操作。如果我们想在每次发生变化时添加一些功能,或者响应某个特定的变化,我们可以侦听一个属性并应用一些逻辑。这意味着 watchers 的名字必须与我们侦听的属性相同。

    当您希望执行操作以响应已发生的更改(例如,对 prop 或 data 属性)时,Watchers 将会派上用场。正如 Vue 文档所提到的,当您想要执行异步操作以响应更改的数据时,watchers 将非常有用。

    在我们的“搜索”示例中,我们可以恢复到最开始的 methods 示例,并为 inputdata 属性设置一个侦听程序,并对任何引发 input 值变化的动作作出反应。

    首先,让我们还原模板以使用 languages data 属性:

    <div id="app">
      <h2>Language Search</h2>
    
      <div class="form-group">
        <input
          type="text"
          v-model="input"
          placeholder="Enter language"
          class="form-control"
        />
      </div>
    
      <ul v-for="(item, index) in languages" class="list-group">
        <li class="list-group-item" :key="item">{{ item }}</li>
      </ul>
    </div>
    

    Vue 实例如下所示:

    new Vue({
      el: "#app",
      data() {
        return {
          input: '',
          languages: []
        }
      },
      watch: {
        input: {
          handler() {
            this.languages = [
              'JavaScript',
              'Ruby',
              'Scala',
              'Python',
              'Java',
              'Kotlin',
              'Elixir'
            ].filter(item => item.toLowerCase().includes(this.input.toLowerCase()))
          },
          immediate: true
        }
      }
    })
    

    在这里,设定侦听属性为一个对象(而不是函数),这样就可以指定一个 immediate 属性,以便在安装组件后侦听属性可以立即触发。这样做的目的,可使列表具有填充的效果。

    结论

    古人云:能力越大,责任就越大。

    Vue 为我们提供了构建优秀应用程序所需的一切,而了解何时使用它们,则是构建用户最喜爱内容的关键。本文介绍了 methods、computed、watcher 三者的用法,但我们的实战项目不可能这么简单,我们在使用 methods、computed、watcher 时,为达到事半功倍的效果,应该合理选择它们最适合的使用场景,就像选择一款最适合你的前端开发工具一样。

    2 条回复    2019-09-27 14:13:09 +08:00
    renmu123
        1
    renmu123  
       2019-09-25 16:23:25 +08:00
    推广
    DKburNIng
        2
    DKburNIng  
       2019-09-27 14:13:09 +08:00
    好长的广告
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5354 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:53 · PVG 15:53 · LAX 23:53 · JFK 02:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.