1. 程式人生 > 其它 >vue中實現元件間的複用

vue中實現元件間的複用

前言

俗話說「懶是程式設計師的美德」。
在越來越注重前端工程化的今天,「Ctrl+C」、「Ctrl+V」的程式碼,雖然用起來一時爽,一旦需要修改就如同面臨火葬場。如何「懶」出效率,是值得思考的問題。
減少程式碼的拷貝,增加封裝複用能力,實現可維護、可複用的程式碼,無疑是我所認為的「懶」的高階境界。
react的高階元件、自定義hooks等等來實現元件複用。當然vue也有對應的方案
所以就藉此機會,談談 Vue 中各種基於元件的複用與實現方式。

繼承

繼承是vue2提供的一個特性,vue3中已經給移除了。
通過關鍵字extends,我們可以讓允許宣告擴充套件另一個元件

var CompA = { ... }
var CompB = {
  extends: CompA,
  data(){return{...}}
}

如上 CompB元件便可以直接訪問CompA元件的屬性和方法,非常的方便
Vue.extend 和這個原理一樣,不過Vue.extend主要是用於編寫全域性外掛用,如Toast
如果看過vue原始碼,就能知道extend的方法實現其實就是js組合式繼承方案

混淆

目前vue2和vue3均支援

// 定義一個混淆物件
const myMixin = {
    created: function () {
        this.hello()
    },
    methods: {
        hello: function () {
            console.log('hello from mixin!')
        }
    }
}

// 元件區域性混入
export default {
    mixins: [myMixin],
    data() { return {...} },
}

在vue3中之所以依然保留,是因為vue3推崇的混合式函式繼承方案(不懂得下邊有說明),無法做到混入複用鉤子函式。

混合式函式

此方案只能用在vue3的混合式api的元件中
此方案解決最大的問題就是 響應式資料(狀態)的複用。
在次之前,普通方法複用我可以提取出去一個js檔案,鉤子複用我可以用mixins,唯獨狀態複用只能extends或 mixins。
extends是基於js繼承方案之組合式繼承,它的弊端大家都知道
mixins弊端,在vue3文件有說明

在 Vue 2 中,mixin 是將部分元件邏輯抽象成可重用塊的主要工具。但是,他們有幾個問題:
Mixin 很容易發生衝突:因為每個 mixin 的 property 都被合併到同一個元件中,所以為了避免 property 名衝突,你仍然需要了解其他每個特性。
可重用性是有限的:我們不能向 mixin 傳遞任何引數來改變它的邏輯,這降低了它們在抽象邏輯方面的靈活性。
為了解決這些問題,我們添加了一種通過邏輯關注點組織程式碼的新方法:組合式 API。

/src/composables/use-student.js

import axios from "axios";
import { ref } from "vue";

const useStudent = () => {
  const student = ref([]);
  const syncStudent = async () => {
    const res = await axios.get("/getStudent");
    student.value = res.data.list;
  };
  return { student, syncStudent };
};

export default useStudent;

/src/App.vue

<script setup>
import useStudent from '../composables/use-student';
const { student, syncStudent } = useStudent();
</script>
<template>
  <div id="app">
    {{ JSON.stringify(student) }}
    <button @click="syncStudent">測試</button>
  </div>
</template>

附贈一個上邊例子的mock

Mock.mock("/getStudent",options=>{  
  return Mock.mock({
    "list|2":[{
      id:()=>Random.guid(),
      name: ()=>Random.cname(),
      age:()=>Random.integer(1,100)
    }]
  })
})