Vue 基礎自查——watch、computed和methods的區別

蜜瓜發表於2021-11-04

1 前言

建立一個Vue例項時,可以傳入一個選項物件

const vm = new Vue({
  data: {
    msg: 'hello'
  },
  computed: {},
  methods: {},
  watch: {}
})

這個選項物件可以指定非常多的選項(或者說屬性),和資料相關的選項有:包括但不限於datamethodscomputedwatch等等

其中methodscomputedwatch都能通過函式來對資料進行處理或作出響應,這三者有差異,但很容易混淆

2 基礎用法

script引入vue.js,下面的程式碼都在如下html中執行

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Methods</title>
    <!-- 引入 vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  </head>
  <body>
    
  </body>
  <script>
    
  </script>
</html>

2.1 methods 方法

methods選項中的定義的函式稱為方法,在Vue例項化的過程中,methods物件中的方法將被混入到Vue例項中,成為Vue例項的方法。可以直接通過Vue例項訪問這些方法

<body>
  <div id="example">
    <!-- 顯示:a:1 -->
    <p>a:{{ plus() }}</p> 
  </div>
</body>
<script>
  const vm = new Vue({
    el: "#example",
    data: {
      a: 0,
    },
    methods: {
      plus: function () {
        return this.a + 1;
      },
    },
  });
  console.log(vm); // 檢視控制檯輸出的vm,可以看到它有一個方法是:plus: ƒ (),⚠️注意是方法
  console.log(vm.plus()); // 直接通過vm例項訪問方法,輸出:1
</script>

需要主動呼叫methods中的函式才能執行a的值改變並不能讓頁面中的<p>a:{{plus()}}</a>跟著更新

2.2 computed 計算屬性

computed選項中定義的函式稱為計算屬性,在Vue例項化的過程中,computed物件中的計算屬性將被混入到Vue例項中,成為Vue例項的同名屬性

<body>
  <div id="example">
    <!-- 顯示:a:1 -->
    <p>a:{{ plus }}</p>
  </div>
</body>
<script>
  const vm = new Vue({
    el: "#example",
    data: {
      a: 0,
    },
    computed: {
      plus: function () {
        return this.a + 1;
      },
    },
  });
  console.log(vm); // // 檢視控制檯輸出的vm,可以看到它有一個屬性是:plus:1,⚠️注意是屬性
</script>

乍一看好像computedmethods功能一樣,確實在這個例子中二者展示效果相同

事實上通過列印vm例項以及訪問方式已經體現出二者的一個不同之處:

  • methods中的函式會成為vm的方法
  • computed中的函式經過計算後會成為vm的同名屬性,屬性值為函式的計算結果,即返回值

另外,和方法不同的是,計算屬效能夠跟著它依賴的資料變化而進行響應式更新,即a變化時,plus屬性也會更新

2.3 watch 偵聽器

watch選項中的鍵值對稱為偵聽器或者說監聽屬性/監聽屬性,鍵是需要觀察的表示式,值是對應的回撥函式(值還可以是其他形式,此處不展開)

在Vue例項化的過程中,這些需要偵聽的變數會被記錄下來,當這些變數發生變化的時候,對應的回撥函式就會執行

<body>
  <div id="example">
    <!-- 顯示:a:1 -->
    <p>a:{{ a }}</p>
  </div>
</body>
<script>
  const vm = new Vue({
    el: "#example",
    data: {
      a: 0,
    },
    watch: {
      a: function () {
        console.log("a發生了變化"); // 因為a的值變了,回撥函式執行
        console.log(this.a);
      },
    },
  });
  vm.a = 1; // 這裡直接手動改變a的值
</script>

3 三者的區別

3.1 方法 VS 計算屬性

除了2.2中已經提到的兩點區別之外,還有最重要的區別是:

  • 計算屬性是基於它們的響應式依賴進行快取的

    即上文中的a發生變化時,才會重新觸發求值函式,否則多次呼叫都會從快取中求值

    這對開銷較大的計算來說非常有用,可以避免重複計算

  • 方法則是呼叫時總會重新執行

下面用表格的形式對這兩者的區別進行總結:

methods computed
Vue例項化後成為vm例項的什麼 成為vm例項上的方法 成為vm例項上的屬性
能否根據依賴的資料進行響應式更新 不能,需要主動呼叫方法
能否快取 不能,每次呼叫重新執行 能,依賴的資料不變,會從快取中取值

3.2 計算屬性 VS 偵聽器

  • 首先最明顯的區別,偵聽器的命名方式是固定的,想要監聽誰,就和誰同名。而方法和計算屬性可任意命名

  • 其次,偵聽器無法主動進行訪問,而另外兩者都能主動訪問

  • 計算屬性和偵聽器的使用場景:

    如果某個值需要通過一個或多個資料計算得到,就使用計算屬性

    偵聽屬性主要是監聽某個值的變化,然後進行需要的邏輯處理;此外當需要在資料變化時執行非同步或開銷較大的操作時,偵聽屬性就比較有用,具體例子可見vue文件-偵聽器

相關文章