簡介
組合式API
,是Vue 3
的新功能,主要是將組件的邏輯關注點,收集在一起,提高邏輯代碼的複用率,方便複雜組件邏輯功能的理解與維護。
實現上,通過setup
組件選項,整合邏輯功能,並返回,在組件模板直接使用。setup
與methods
、data
、computed
等是向下兼容的。
需要注意的是: 在setup
中不能使用this
,會找不到組件的實例,因爲setup
選項是在組件創建前執行的。methods
、data
、computed
定義的屬性、方法均無法在setup
中被獲取。
接下來我們通過一個簡單的示例來了解組合式API的關注點分離、邏輯功能複用;
示例
示例: 一個計數器,每次遇到偶數的時候,加入列表進行展示;可排序翻轉、可修改列表數據。
邏輯功能:
- 基於步幅的累加
- 列表數據更新(添加)
- 列表數據排序&翻轉
- 列表數據的修改
實現
<script>export default { ///定義組件屬性 props: { initialCount: { type: Number, required: false, default: 0, }, step: { type: Number, default: 1 } }, data() { return { count: this.initialCount,//功能1 stepValue : this.step,//功能1 captureValues: [],//功能2、3、4 }; }, methods: { increment() {//功能1 this.count += this.stepValue; }, sortCaptureValues() {//功能2 this.captureValues.sort((a, b) => a > b).reverse(); }, updateCaptureValues() {//功能3 if (this.isEven) { this.captureValues.push(this.count); } }, changeCaptureValues() {//功能4 this.captureValues = this.captureValues.map((a) => a * 10); }, }, computed: { isEven() {//功能3 return this.count % 2 == 0; }, }, watch: { count(newVal, oldVal) { this.updateCaptureValues();//功能3 }, }, onmounted() { console.log("🔥"); },};</script>
可以看到組件中功能實現是分散在不同的組件選項中,當功能很多很複雜的時候,代碼的可讀性也會大大降低。多個組件間,相同邏輯功能複用不易。 Vue 2
中,雖然可通過mixins
解決,但mixins
容易出現命名衝突等問題。
setup 實現
接下來,我們基於組合式API
來實現,代碼如下:
<script>import { ref, computed, watch } from "vue";export default { ///定義組件屬性 props: { initialCount: { type: Number, required: false, default: 0, }, step: { type: Number, default: 1, }, }, setup(props) { ///功能1:基於步幅的累加 const count = ref(props.initialCount); const stepValue = ref(props.step); const increment = () => (count.value += stepValue.value); ///功能2: 列表數據更新(添加) const captureValues = ref([]); const isEven = computed(() => count.value % 2 === 0); const updateCaptureValues = () => { console.log(isEven); if (isEven.value === true) { captureValues.value.push(count.value); } }; ///功能3: 列表數據排序&翻轉 const sortCaptureValues = () => { captureValues.value.sort((a, b) => a > b).reverse(); }; ///功能4:列表數據的修改 const changeCaptureValues = () => { captureValues.value = captureValues.value.map((a) => a * 10); }; ///監聽count watch(count, updateCaptureValues); return { count, stepValue, increment, isEven, captureValues, updateCaptureValues, sortCaptureValues, changeCaptureValues, }; },};</script>
可以清楚的看到代碼邏輯功能更加聚焦,可讀性增強。 需要注意的是,組件中的數據需要通過ref
變爲響應式的。
功能複用
基於setup
的實現方式,我們可將功能提取到獨立的js
文件中,以便其他組件複用。
///文件路徑: src/composables/useIncrementimport {ref,computed} from 'vue'///功能1:基於步幅的累加export default function useIncrement(initialCount,step) { const count = ref(initialCount) const stepValue = ref(step) const increment = () => count.value += stepValue.value return { count, stepValue, increment }} ///功能2: 列表數據更新(添加)export function useUpdateValues(count) { const captureValues = ref([]); const isEven = computed(() => count.value % 2 === 0); const updateCaptureValues = () => { if (isEven.value === true) { captureValues.value.push(count.value); } }; return { captureValues, updateCaptureValues, }}///功能3: 列表數據排序&翻轉export function useSortValues(values) { const sortCaptureValues = () => { values.value.sort((a, b) => a > b).reverse(); }; return { sortCaptureValues }}///功能4:列表數據的修改export function useChangeValues(values,base) { const changeCaptureValues = () => { values.value = values.value.map((a) => a * base); }; return { changeCaptureValues }}
再將提取的功能函數引入到我們Counter
組件中:
<script>import {watch,onMounted} from "vue";import useIncrement, {useUpdateValues,useSortValues,useChangeValues} from "../composables/useIncrement";export default { ///定義組件屬性 props: /*...*/ setup(props) { ///累加 const {count, stepValue, increment} = useIncrement(props.initialCount, props.step) ///添加到列表 const {captureValues,updateCaptureValues} = useUpdateValues(count) ///排序數據 const {sortCaptureValues} = useSortValues(captureValues) ///改變數據 const { changeCaptureValues } = useChangeValues(captureValues,10) ///監聽count watch(count, updateCaptureValues); ///生命週期 onMounted(()=>console.log("已掛載組件")) return { count, stepValue, increment, captureValues, updateCaptureValues, sortCaptureValues, changeCaptureValues, }; },};</script>
這樣其他的組件就可以複用提取功能了,比如:SimpleCounter
組件複用基於步幅的累加功能。
<template> <button @click="increment" > {{count}}</button></template><script>import useIncrement from "../composables/useIncrement";export default { setup(props) { return { ...useIncrement(0,2) // 增幅爲2,初始值爲0,的計數器 } }}</script>
或者使用<script setup>
單文件組件中使用組合式API
的語法糖:
<template> <button @click="increment" > {{count}}</button></template><script setup>import useIncrement from "../composables/useIncrement";const {count, increment} = useIncrement(0,2) // 增幅爲2 ,初始值爲0,的計數器</script>
參考資料
https://v3.cn.vuejs.org/guide/composition-api-introduction.html