Vue: methods,computed 计算属性 以及 watch 之间的区别

Vue app 可以有 4 个配置选项:

  1. data
  2. methods
  3. computed
  4. watch

即:

const app = Vue.createApp({
  data() {
    return { ... };
  },
  computed: {
    // ...
  },
  methods: {
    // ...
  },
  watch: {
    // ...
  }
});
app.mount("#root");

视频截图,
Vue: methods,computed 计算属性 以及 watch 之间的区别_第1张图片

计算属性

如果不考虑性能,计算属性 computed 可以全部放到 methods 里。
使用计算属性的目的只是为了改善性能。
原因是,HTML 页面上发生任何改变,v-bind, v-html, {{ }} 中的任何方法,即任意非事件绑定的方法都将被重新执行,影响 performance,因为 Vue 不清楚 methods 里方法的依赖关系。

以下是一段简单的代码,点击两个按钮,分别对一个数字加或减,也可以输入namelastname, 二者相加输出 fullname。

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Basicstitle>
    <link
      href="https://fonts.googleapis.com/css2?family=Jost:wght@400;700&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
    <script src="https://unpkg.com/vue@next" defer>script>
    <script src="app.js" defer>script>
  head>
  <body>
    <header>
      <h1>Vue Eventsh1>
    header>
    <section id="events">
      <h2>Events in Actionh2>
      <button v-on:click="add(5)">Addbutton>
      <button v-on:click="reduce(5)">Reducebutton>
      <p>Result: {{ counter }}p>
      <input type="text" v-model="name" />
      <input type="text" v-model="lastName" />
      <p>Your name: {{outputFullname()}}p>
    section>
  body>
html>
// app.js
const app = Vue.createApp({
  data() {
    return {
      counter: 0,
      name: "",
      lastName: "",
    };
  },
  methods: {
    outputFullname() {
      console.log("outputFullname executed!");
      if (this.name === "") {
        return "";
      }
      return this.name + " " + this.lastName;
    },
    add(x) {
      this.counter += x;
    },
    reduce(x) {
      this.counter -= x;
    },
    setName(e, lastName) {
      this.name = e.target.value;
    },
  },
});
app.mount("#events");

输出 fullname 是通过调用 methods 里的 outputFullname() 实现的,表面上看代码 ok,没有任何问题。
但是如果打开console,点击 add 或者 reduce 按钮加减数字,就会发现 outputFullname() 也在执行,虽然数字和姓名两个部分二者是完全独立的,没有任何关联。页面上的发生任何变化,此方法都将被重新执行一遍,这就是问题所在。因为 Vue 无法知道这个method 即 outputFullname() 究竟在干什么。
显然这是一个需要优化的地方,需要使得数字在进行加减,即点击 add 或者 reduce 按钮时,outputFullname() 不会执行。
Vue: methods,computed 计算属性 以及 watch 之间的区别_第2张图片
优化的方法就是使用计算属性,将 outputFullname() 改用 computed 即计算属性实现,也就是将 outputFullname() 的逻辑放到 computed 里。计算属性实质上类似于方法,但是有一个重要的区别:Vue 明白它们的依赖,仅仅当某个依赖变化时才会重新执行。

HTML 修改:

<p>Your name: {{fullname}}p>

app.js 增加 computed 属性,outputFullname() 不再使用。

  data() {
	// ....
  },
  computed: {
    fullname() {
      console.log("fullname in computed executed!");
      if (this.name === "") {
        return "";
      }
      return this.name + " " + this.lastName;
    },
  },
  methods: {
    // ...
  }

计算属性不能调用

可以像使用 data properties 一样使用 computed properties, computed properties 里的方法的命名类似于数据属性,所以 computed 里使用的方法名称是 fullname, 而非 outputFullname, 同样,计算属性被当成数据属性使用,因此计算属性不能调用,下面的 fullname不能加括号

<p>Your name: {{fullname}}p>

改为使用计算属性,当点击 reduce 或者 add,不再出现之前的方法无条件重复执行问题:
Vue: methods,computed 计算属性 以及 watch 之间的区别_第3张图片

watch

模板里不会直接使用 watch,使用 watch 可以监视数据属性或者计算属性的变化,从而执行某些操作对数据的改变作出反应。watch 里的方法名重复使用任意 data 属性名或者 computed 属性名,watch 里的方法由于返回值不会被用到,因此没有 return 语句。

watch: {
  any_name_of_data_or_computed_properties (newValue, oldValue) { ... }
}

watch 可以接受两个参数,newValue 是最新值,oldValue 是上一次的值,如果代码需要可以写两个,newValueoldValue 也可以改成别的名称。

下面的代码,任意点击 add, 或者 reduce 按钮若干次,如果 counter 大于 50,Vue 将在两秒之后自动重置 counter0

const app = Vue.createApp({
  data() {
    return {
      counter: 0,
      name: "",
      lastName: "",
    };
  },
  computed: {
  },
  watch: {
    counter(v) {
      if (v > 50) {
        const that = this;
        setTimeout( ()=> {
          that.counter = 0;
        }, 2000);
      }
    },
  },
  methods: {
   // ...
  },
});
app.mount("#events");

你可能感兴趣的:(vue)