截至目前,組合式函數(shù)應(yīng)該是在VUE 3應(yīng)用程序中組織業(yè)務(wù)邏輯最佳的方法。它讓我們可以把一些小塊的通用邏輯進(jìn)行抽離、復(fù)用,使我們的代碼更易于編寫、閱讀和維護(hù)。
一. 什么是“組合式函數(shù)”?
根據(jù)官方文檔說明,在 Vue 應(yīng)用的概念中,“組合式函數(shù)”是一個(gè)利用 Vue 組合式 API 來封裝和復(fù)用有狀態(tài)邏輯的函數(shù)。
這就意味著,任何有狀態(tài)邏輯,并且使用了響應(yīng)式處理的邏輯都可以轉(zhuǎn)換成組合式函數(shù)。這和我們平時(shí)抽離封裝的公共方法還是有一些區(qū)別的。我們封裝的公共方法往往是無狀態(tài)的:它在接收一些輸入后立刻返回所期望的輸出。而組合式函數(shù)往往是和狀態(tài)邏輯關(guān)聯(lián)的。簡(jiǎn)單的理解就是“**可復(fù)用邏輯的集合,專注點(diǎn)分點(diǎn)**”
二.?vue3 自定義hooks
1. 為什么Vue3要用自定義Hook?
結(jié)論:就是為了讓Compoosition Api
更好用更豐滿,讓寫Vue3更暢快! 其實(shí)這個(gè)問題更深意義是為什么Vue3比Vue2更好!無外呼性能大幅度提升,其實(shí)編碼體驗(yàn)也是Vue3的優(yōu)點(diǎn)**Composition Api
的引入(解決Option Api在代碼量大的情況下的強(qiáng)耦合)** 讓開發(fā)者有更好的開發(fā)體驗(yàn)。
2. 怎么理解自定義Hooks
以函數(shù)形式抽離一些可復(fù)用的方法像鉤子一樣掛著,隨時(shí)可以引入和調(diào)用,實(shí)現(xiàn)高內(nèi)聚低耦合的目標(biāo);
- 將可復(fù)用功能抽離為外部JS文件
- 函數(shù)名/文件名以u(píng)se開頭,形如:useXX
- 引用時(shí)將響應(yīng)式變量或者方法顯式解構(gòu)暴露出來如:
const {nameRef,F(xiàn)n} = useXX()
(在setup函數(shù)解構(gòu)出自定義hooks的變量和方法)
3. 實(shí)例
簡(jiǎn)單的加減法計(jì)算,將加法和減法抽離為2個(gè)自定義Hooks,并且相互傳遞響應(yīng)式數(shù)據(jù)
- 加法功能-Hook
import { ref, watch } from 'vue';
const useAdd= ({ num1, num2 }) =>{
const addNum = ref(0)
watch([num1, num2], ([num1, num2]) => {
addFn(num1, num2)
})
const addFn = (num1, num2) => {
addNum.value = num1 + num2
}
return {
addNum,
addFn
}
}
export default useAdd
- 減法功能-Hook
import { ref, watch } from 'vue';
export function useSub ({ num1, num2 }){
const subNum = ref(0)
watch([num1, num2], ([num1, num2]) => {
subFn(num1, num2)
})
const subFn = (num1, num2) => {
subNum.value = num1 - num2
}
return {
subNum,
subFn
}
}
- 加減法計(jì)算組件
<template>
<div>
num1:<input v-model.number="num1" style="width:100px" />
<br />
num2:<input v-model.number="num2" style="width:100px" />
</div>
<span>加法等于:{{ addNum }}</span>
<br />
<span>減法等于:{{ subNum }}</span>
</template>
?
<script setup>
import useAdd from './useAdd.js' //引入自動(dòng)hook
import { useSub } from './useSub.js' //引入自動(dòng)hook
?
const num1 = ref(2)
const num2 = ref(1)
//加法功能-自定義Hook(將響應(yīng)式變量或者方法形式暴露出來)
const { addNum, addFn } = useAdd({ num1, num2 })
addFn(num1.value, num2.value)
//減法功能-自定義Hook (將響應(yīng)式變量或者方法形式暴露出來)
const { subNum, subFn } = useSub({ num1, num2 })
subFn(num1.value, num2.value)
</script>
3. 自定義Hooks 還可以傳參
接上面的例子
平均功能-Hook?
import { ref, watch } from "vue";
export function useAverage(addNum) {
const averageNum = ref(0);
watch(addNum, (addNum) => {
averageFn(addNum);
});
const averageFn = (addNum) => {
averageNum.value = addNum / 2;
};
return {
averageNum,
averageFn,
};
}
組件內(nèi):
//加法功能-自定義Hook(將響應(yīng)式變量或者方法形式暴露出來)
const { addNum, addFn } = useAdd({ num1, num2 })
addFn(num1.value, num2.value)//主動(dòng)調(diào)用,返回最新addNum
//平均功能-自定義Hook- hook傳入?yún)?shù)值來其他hook暴露出來的變量
const { averageNum, averageFn} = useAverage(addNum)
averageFn(addNum.value)
三 .自定義Hooks 實(shí)現(xiàn)minxins
Vue3自定義Hooks和Vue2時(shí)代Mixin的關(guān)系
Mixin不足
在 Vue 2 中,mixin 是將部分組件邏輯抽象成可重用塊的主要工具。但是,他們有幾個(gè)問題:
1、Mixin 很容易發(fā)生沖突:因?yàn)槊總€(gè) mixin 的 property 都被合并到同一個(gè)組件中,所以為了避免 property 名沖突,你仍然需要了解其他每個(gè)特性。
2、可重用性是有限的:我們不能向 mixin 傳遞任何參數(shù)來改變它的邏輯,這降低了它們?cè)诔橄筮壿嫹矫娴撵`活性。
Vue2 中的mixins混入器寫法缺點(diǎn)
//minxins.js 文件
export default{
data(){
return{
message:'混入對(duì)象',
name:'zhangsan000'
}
},
methods: {
logMessage() {
console.log('打印message', this.message);
}
}
}
組件:
// 使用
import minxins from "./common/minxins";
import minxins1 from "./common/minxins1"; // 舉例
import minxins2 from "./common/minxins2"; // 舉例
export default{
mixins: [minxins, minxins1, minxins2], //可混入多個(gè)文件
data(){
return{
message:'混入對(duì)象新的',
bar:'bar',
}
},
created(){
this.logMessage(); // 打印 '混入對(duì)象新的'
console.log('created組件鉤子被調(diào)用')
},
?上面的代碼 可以看出:?mixins 的深度合并非常隱式,讓代碼邏輯更難理解和調(diào)試,具體表現(xiàn)為如下幾點(diǎn):
- 數(shù)據(jù)來源不清晰:當(dāng)使用了多個(gè)minxins時(shí), property來自哪個(gè) mixin變得不清晰,這使追溯實(shí)現(xiàn)和理解組件行為變得困難。
- 命名沖突:因?yàn)槊總€(gè)特性的屬性都被合并到同一個(gè)組件中,組件內(nèi)同名的屬性或方法會(huì)把mixins里的覆蓋掉。
- 可重用性有限:?多個(gè)minxin需要依賴共享的 property鍵名來進(jìn)行相互作用,這使得它們隱性地耦合在一起。而一個(gè)組合式函數(shù)的返回值可以作為另一個(gè)組合式函數(shù)的參數(shù)被傳入,像普通函數(shù)那樣。
1. Mixin難以追溯的方法與屬性!Vue3自定義Hooks卻可以
Vue3自定義Hooks, 引用時(shí)將響應(yīng)式變量或者方法顯式暴露出來如:
const {nameRef,F(xiàn)n} = useXX()
2.?Mixin同名變量會(huì)被覆蓋,Vue3自定義Hook可以在引入的時(shí)候?qū)ν兞恐孛?/h4>
- mixin
export default {
mixins: [ addMixin, subMixin], //組件內(nèi)混入加法和減法Mixin
mounted(){
this.add(num1,num2) //調(diào)用加法addMixin內(nèi)部的add方法
this.sub(num1,num2) //調(diào)用減法subMixin內(nèi)部的sub方法
}
}
export default {
mixins: [ addMixin, subMixin], //組件內(nèi)混入加法和減法Mixin
mounted(){
this.add(num1,num2) //調(diào)用加法addMixin內(nèi)部的add方法
this.sub(num1,num2) //調(diào)用減法subMixin內(nèi)部的sub方法
}
}
?如果this.add(num1,num2)
和?this.sub(num1,num2)
?計(jì)算的結(jié)果返回的同名變量totalNum,由于JS單線程,后面引入的會(huì)覆蓋前面的,totalNum最終是減法sub的值
- Vue3自定義Hooks
如上面例子
//加法功能-自定義Hook(將響應(yīng)式變量或者方法形式暴露出來)
const { addNum, addFn } = useAdd({ num1, num2 })
addFn(num1.value, num2.value)
//減法功能-自定義Hook (將響應(yīng)式變量或者方法形式暴露出來)
const { subNum, subFn } = useSub({ num1, num2 })
subFn(num1.value, num2.value)
在Vue3自定義Hooks中,雖然加法和減法Hooks都返回了totalNum,但是利用ES6對(duì)象解構(gòu)很輕松給變量重命名?
所以在vue3中是不推薦使用mixins 這種方式
?Vue3 composition API寫 法寫 minxins 類功能
//useHello.js
import { ref } from 'vue';
export function useHello() {
let message = ref('組合函數(shù)api');
const logMessage = (val) => {
console.log(val + message.value);
};
return { message, logMessage };
}
組件使用時(shí)
<template>
<div class="app-container home">
<p>{{ message }}</p>
</div>
</template>
<script setup name="Index">
import { useHello } from './useHello.js';
let name = ref('hello');
// let message = ref('混入對(duì)象新'); //異常提示 無法重新聲明塊范圍變量“message”
const { message, logMessage } = useHello();
onMounted(() => {
logMessage(name.value);
});
</script>
上面代碼可以看出:
- 當(dāng)使用了多個(gè)組合式封裝的屬性時(shí),追溯來源清晰明了。
- 命名沖突會(huì)直接提示命名重復(fù)了的異常。
- 不存在 Vue2那種 隱式的跨 minxin交流,因?yàn)轫?yè)面引用了重復(fù)變量直接會(huì)提示。
- 使用函函數(shù)式編程, 函數(shù)內(nèi)部的變量在打包的時(shí)候,壓縮器會(huì)把函數(shù)內(nèi)部的變量壓成 var a,b,c,d 之類的。而對(duì)象中的屬性key 值,主流打包工具壓縮器沒有簡(jiǎn)化對(duì)象key值名字。所以函數(shù)式編程打包包體相對(duì)會(huì)更小一些。
四 總結(jié)
Vue2時(shí)代Option Api ,data、methos、watch.....
分開寫,這種是碎片化的分散的,代碼一多就容易高耦合,維護(hù)時(shí)來回切換代碼是繁瑣的!
Vue3時(shí)代Composition Api
,通過利用各種Hooks和自定義Hooks將碎片化的響應(yīng)式變量和方法按功能分塊寫,實(shí)現(xiàn)高內(nèi)聚低耦合
形象的講法:Vue3自定義Hooks是組件下的函數(shù)作用域的,而Vue2時(shí)代的Mixins是組件下的全局作用域。全局作用域有時(shí)候是不可控的,就像var和let這些變量聲明關(guān)鍵字一樣,const和let是var的修正。Composition Api正是對(duì)Vue2時(shí)代Option Api 高耦合和隨處可見this的黑盒的修正,Vue3自定義Hooks是一種進(jìn)步。
把Mixin和自定義Hook進(jìn)行比較,一個(gè)是Option Api的體現(xiàn),一個(gè)是Composition Api的體現(xiàn)。如果能理解高內(nèi)聚低耦合的思想,那么就能理解為什么Vue3是使用Composition Api,并通過各種自定義Hooks使代碼更強(qiáng)壯。
五.補(bǔ)充
由Ref組成的對(duì)象
以使用可組合的函數(shù)式,同時(shí)獲得ref和reactive的好處
import { ref,reactive}from 'vue'
function useMouse(){
return {
x:ref(0),
y:ref(0),
}
}
const {x} = useMouse()
const mouse = reactive(useMouse())
mouse.x === x.value //true
1.可以直接使用es6解構(gòu)其中的Ref使用
2.根據(jù)使用方式,當(dāng)想要自動(dòng)解包的功能時(shí),可以使用 reactive將其轉(zhuǎn)換為對(duì)象
將異步操作轉(zhuǎn)換為“同步”
使用組合式API,我們甚至可以將異步操作轉(zhuǎn)換為“同步”的
異步
const data = await fetch('https://196.198.1.0/use/').then(r=>r.json())
// use data
組合式api
const {data} = await useFetch('https://196.198.1.0/use/').json()
const user_url = computed(()=>data.value?data.value.user_url:'')
先建立數(shù)據(jù)間的“連結(jié)”,然后再等待異步請(qǐng)求返回將數(shù)據(jù)填充。概念和react 中的SWR(stale-while-revalidate)類似。
狀態(tài)共享
由于組合式API天然提供的靈活性,狀態(tài)可以獨(dú)立于組件被創(chuàng)建并使用
但是不兼容ssr(服務(wù)器渲染)?
兼容SSR的狀態(tài)共享
使用provide和inject 來共享應(yīng)用層面的狀態(tài)。
文章來源:http://www.zghlxwxcb.cn/news/detail-714809.html
六.?引用
vue3中的自定義hook函數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-714809.html
到了這里,關(guān)于Vue3 組合式函數(shù),實(shí)現(xiàn)minxins的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!