Vue3.0 所采用的 Composition Api 與 Vue2.x 使用的 Options Api 有什么不同?


 

 

開始之前

Composition API 可以說是Vue3最大的特點,那么為什么要推出Composition Api,解決了什么問題?

通常使用Vue2開發的項目,普遍會存在以下問題:

  • 代碼的可讀性隨着組件變大而變差
  • 每一種代碼復用的方式,都存在缺點
  • TypeScript支持有限

以上通過使用Composition Api都能迎刃而解

正文

一、Options Api

Options API,即大家常說的選項API,即以vue為后綴的文件,通過定義methodscomputedwatchdata等屬性與方法,共同處理頁面邏輯

如下圖:

 

 

可以看到Options代碼編寫方式,如果是組件狀態,則寫在data屬性上,如果是方法,則寫在methods屬性上...

用組件的選項 (datacomputedmethodswatch) 組織邏輯在大多數情況下都有效

然而,當組件變得復雜,導致對應屬性的列表也會增長,這可能會導致組件難以閱讀和理解

二、Composition Api

在 Vue3 Composition API 中,組件根據邏輯功能來組織的,一個功能所定義的所有 API 會放在一起(更加的高內聚,低耦合)

即使項目很大,功能很多,我們都能快速的定位到這個功能所用到的所有 API

 

 

三、對比

下面對Composition ApiOptions Api進行兩大方面的比較

  • 邏輯組織
  • 邏輯復用

邏輯組織

Options API

假設一個組件是一個大型組件,其內部有很多處理邏輯關注點(對應下圖不用顏色)

 

 

可以看到,這種碎片化使得理解和維護復雜組件變得困難

選項的分離掩蓋了潛在的邏輯問題。此外,在處理單個邏輯關注點時,我們必須不斷地“跳轉”相關代碼的選項塊

Compostion API

Compositon API正是解決上述問題,將某個邏輯關注點相關的代碼全都放在一個函數里,這樣當需要修改一個功能時,就不再需要在文件中跳來跳去

下面舉個簡單例子,將處理count屬性相關的代碼放在同一個函數了

function useCount() {
    let count = ref(10);
    let double = computed(() => {
        return count.value * 2;
    });

    const handleConut = () => {
        count.value = count.value * 2;
    };

    console.log(count);

    return {
        count,
        double,
        handleConut,
    };
}

組件上中使用count

export default defineComponent({
    setup() {
        const { count, double, handleConut } = useCount();
        return {
            count,
            double,
            handleConut
        }
    },
});

再來一張圖進行對比,可以很直觀地感受到 Composition API在邏輯組織方面的優勢,以后修改一個屬性功能的時候,只需要跳到控制該屬性的方法中即可

 

 

 

邏輯復用

Vue2中,我們是用過mixin去復用相同的邏輯

下面舉個例子,我們會另起一個mixin.js文件

export const MoveMixin = {
  data() {
    return {
      x: 0,
      y: 0,
    };
  },

  methods: {
    handleKeyup(e) {
      console.log(e.code);
      // 上下左右 x y
      switch (e.code) {
        case "ArrowUp":
          this.y--;
          break;
        case "ArrowDown":
          this.y++;
          break;
        case "ArrowLeft":
          this.x--;
          break;
        case "ArrowRight":
          this.x++;
          break;
      }
    },
  },

  mounted() {
    window.addEventListener("keyup", this.handleKeyup);
  },

  unmounted() {
    window.removeEventListener("keyup", this.handleKeyup);
  },
};

然后在組件中使用

<template>
  <div>
    Mouse position: x {{ x }} / y {{ y }}
  </div>
</template>
<script>
import mousePositionMixin from './mouse'
export default {
  mixins: [mousePositionMixin]
}
</script>

使用單個mixin似乎問題不大,但是當我們一個組件混入大量不同的 mixins 的時候

mixins: [mousePositionMixin, fooMixin, barMixin, otherMixin]

會存在兩個非常明顯的問題:

  • 命名沖突
  • 數據來源不清晰

現在通過Compositon API這種方式改寫上面的代碼

import { onMounted, onUnmounted, reactive } from "vue";
export function useMove() {
  const position = reactive({
    x: 0,
    y: 0,
  });

  const handleKeyup = (e) => {
    console.log(e.code);
    // 上下左右 x y
    switch (e.code) {
      case "ArrowUp":
        // y.value--;
        position.y--;
        break;
      case "ArrowDown":
        // y.value++;
        position.y++;
        break;
      case "ArrowLeft":
        // x.value--;
        position.x--;
        break;
      case "ArrowRight":
        // x.value++;
        position.x++;
        break;
    }
  };

  onMounted(() => {
    window.addEventListener("keyup", handleKeyup);
  });

  onUnmounted(() => {
    window.removeEventListener("keyup", handleKeyup);
  });

  return { position };
}

在組件中使用

<template>
  <div>
    Mouse position: x {{ x }} / y {{ y }}
  </div>
</template>

<script>
import { useMove } from "./useMove";
import { toRefs } from "vue";
export default {
  setup() {
    const { position } = useMove();
    const { x, y } = toRefs(position);
    return {
      x,
      y,
    };

  },
};
</script>

可以看到,整個數據來源清晰了,即使去編寫更多的 hook 函數,也不會出現命名沖突的問題

小結

  • 在邏輯組織和邏輯復用方面,Composition API是優於Options API
  • 因為Composition API幾乎是函數,會有更好的類型推斷。
  • Composition API對 tree-shaking 友好,代碼也更容易壓縮
  • Composition API中見不到this的使用,減少了this指向不明的情況
  • 如果是小型組件,可以繼續使用Options API,也是十分友好的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM