關(guān)于vue3?option?api新玩法分享
可能一些朋友看到標題,瞬間就不淡定了,vue3+option api,在大家都在使用setup做組合式API的今天,這不就是開歷史的倒車嗎?別急啊,我們這么做,也是有苦衷的。

這是2個月之前在一篇介紹script setup的文章里面,我發(fā)布一個評論。事情就如同評論所說,考慮到成員之間水平不一樣,太靈活了,你寫代碼煮面條我也煮面條,彼此之間反而互相看不懂代碼了。那做eslint規(guī)范約束吧,約束到最后得到一個長得像option api但效果又沒有option api好的規(guī)范,最終團隊默默退回了option api了。
可能有些朋友還不知道什么是option api,什么是setup吧?這里先簡單解釋一下,所謂option api,就是vue2的那套寫法:
export default {
data(){
return {/*...*/}
},
methods:{},
mounted(){}
}
而所謂script setup或者組合式api,是vue3的一個新寫法,它允許我們在setup作用域下完成整個頁面的邏輯編寫:
export default defineComponent({
setup(){
const a = ref(0)
onMounted(()=>{
a.value = 100
})
return {
a
}
}
})
// 或者在<script setup>里面直接寫
const a = ref(0)
onMounted(()=>{
a.value = 100
})
正當我們感嘆時代變化真快,團隊無法在時代的新潮流玩耍的時候,一個突入其來的bug,為團隊成員打開了新思路。
事情是這樣的,團隊一個成員在做組件集成monaco editor(一個微軟開發(fā)的代碼編輯器組件)的時候,發(fā)現(xiàn)退出頁面的時候直接將瀏覽器卡死了。一般瀏覽器卡死,肯定是js死循環(huán)造成的,于是整個團隊開始對他的代碼進行review,仔細檢查每一處循環(huán),查看每一處判斷條件,生怕漏了哪一個可能照成判斷逃逸導致循環(huán)無法停止的地方。
然而他的代碼在option api下顯得規(guī)規(guī)矩矩,review起來通俗易懂,在代碼實現(xiàn)上找不到可以挑剔的地方。但是卡死瀏覽器的問題依然存在,總不該是vue3或者是monaco的問題吧?于是祭出注釋debug法,從beforeUnmount開始注釋掉:
export default defineComponent({
...
beforeUnmount() {
// console.log("dispose");
// this.edt && this.edt.dispose();
}
})
this.edt是monaco editor的實例對象。真的是幸運,第一次注釋就找到原因,退出頁面不卡死了。但是引起瀏覽器卡死的,是monaco的釋放內(nèi)存?
這肯定不可能,于是我重新讀代碼,直到眼光放在this.edt的聲明上:
export default defineComponent({
data(){
return {
...
edt:null as editor.IStandaloneCodeEditor|null
}
}
...
mounted(){
this.edt = editor.create(...)
}
})
注釋掉data里面的edt聲明,同時恢復在beforeUnmount時釋放內(nèi)存。這時候ts拋錯了,edt在this里面不存在。好在vite并不會理會ts的錯誤,頁面正常運行,退出時也不會引起瀏覽器卡死。那么答案呼之欲出,罪魁禍首就是你,vue的響應式變量功能!我猜測是monaco的editor實例里有一堆相互引用的屬性,原本沒有proxy的情況下,銷毀就銷毀了,但是加上了vue的proxy之后,相互引用層層嵌套導致一直無法銷毀造成死循環(huán)。
而在vue2寫js的時候,這些第三方庫都是很隨便的用一個運行時this.xxx去掛載。但是vue3對ts的支持加強,團隊開始使用ts,之前運行時this.xxx的用法會報錯,于是很多成員為了解決這個錯誤,同時又想獲得類型提示,就直接在data里面聲明這個屬性。
像這次,就是將第三方庫操作對象掛載在data里面,恰好跟proxy結(jié)合導致bug的發(fā)生。既然在沒有proxy的環(huán)境下執(zhí)行是正常的,那么option api里有沒有可以掛載無響應屬性的地方呢?
“為什么不直接掛在setup里面呢?setup里面的變量不加ref的話是沒有響應式的,我們不在setup里面寫邏輯,不代表我們不能用setup呀。”
團隊里面另一位成員一語驚醒夢中人:
export default defineComponent({
setup(){
const edt:editor.IStandaloneCodeEditor|null = null
return {
edt
}
},
data(){
return {
...
// edt:null as editor.IStandaloneCodeEditor|null
}
}
...
mounted(){
this.edt = editor.create(...)
},
beforeUnmount() {
console.log("dispose");
this.edt && this.edt.dispose();
}
})

這樣,ts不報錯了,也可以進行類型提示。頁面也不卡死了,第三庫如愿以償?shù)脑跊]有proxy的作用下運行。會寫hook的同學笑了,后面可以把邏輯抽象到ts里面了。組合式api寫不好的同學也沒有灰心,因為還是在他熟悉的option api體系下開發(fā),而且可以寫得更加出色。
把setup當作option api的一部分,把不會用到模板里的變量掛在setup里,把頁面模板會用到的變量掛在data里,而通過this都能訪問到兩者,也可以為兩者提供類型檢查。相比vue2來說,團隊成員代碼里不會再出現(xiàn)運行時掛載最終導致相互覆蓋的事情發(fā)生,這無疑已經(jīng)是一個巨大的進步。
這就是我要說的option api的新玩法,也是vue3的新功能。因為團隊的不適應,暫時放棄了setup里寫邏輯的能力,改用于掛載非響應式變量和抽象出來的hook。
但更重要的是我們要有一個認識,在代碼世界里面沒有必要把事物對立起來,彼此之間都有長處,那應該是取決于自身的情況把彼此的長處容納進來,即不要為了新而新,也無須因為舊而排斥,適合自己的才是最好的。
總結(jié)
到此這篇關(guān)于vue3 option api新玩法的文章就介紹到這了,更多相關(guān)vue3 option api新玩法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中使用Echarts儀表盤展示實時數(shù)據(jù)的實現(xiàn)
這篇文章主要介紹了Vue中使用Echarts儀表盤展示實時數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11
vue如何使用moment處理時間戳轉(zhuǎn)換成日期或時間格式
這篇文章主要給大家介紹了關(guān)于vue如何使用moment處理時間戳轉(zhuǎn)換成日期或時間格式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者vue具有一定的參考學習價值,需要的朋友可以參考下2022-03-03

