關(guān)于Vue3實(shí)踐的一些問題清單
本文轉(zhuǎn)載自微信公眾號「微醫(yī)大前端技術(shù)」,作者黃琴 。轉(zhuǎn)載本文請聯(lián)系微醫(yī)大前端技術(shù)公眾號。
前言
瞪瞪,胖琴的第三篇文章來襲!近期在自己的規(guī)劃中列著一份 vue3 清單。關(guān)于 vue3,雖然之前很早就看過了,但是也只是簡單的了解一番寫了幾個(gè)小 demo,而且我司的主要技術(shù)棧也是 vue, 近期趁著這股學(xué)習(xí)的勁,趕緊向上申請了一個(gè)內(nèi)部項(xiàng)目,想著用 vue3 實(shí)踐一波,希望這一篇總結(jié)對一些小伙伴提供一些幫助。
以下主要會從兩部分去做總結(jié),一部分是可能混淆的點(diǎn) or 一些常見的問題,另外一部分是實(shí)踐過程中遇到的坑點(diǎn)/注意點(diǎn)。
關(guān)于 vue3 的一些疑問點(diǎn)
1: 使用了 Vue3,是否都要遵循用 Composition API 的形式去寫頁面?
答案是否定的。需要注意一點(diǎn):Vue3 并沒有廢棄 Options API,甚至還會全力支持兼容 Vue2 語法的工作。而 CompositionAPI 出現(xiàn)的背景主要是為了解決邏輯抽象和和復(fù)用的問題,但不意味著它成為了 Vue3 的標(biāo)準(zhǔn)。So,如何區(qū)分場景使用Options API or Composition API主要看業(yè)務(wù)邏輯的復(fù)雜程序,例如一些簡單的 toast/button 等基礎(chǔ)組件,用options API形式會更加清晰和簡潔。而相對復(fù)雜的業(yè)務(wù)邏輯,可以用Composition API,可以把單獨(dú)一塊邏輯抽離到一個(gè)模塊,通過 hook 函數(shù)的方式去解決。
2: Vue3 中混用 Options API 和 Composition API 會不會對性能產(chǎn)生影響?
不會。其實(shí)從問題 1 就可以明顯地看出來并不會對性能產(chǎn)生任何影響。不應(yīng)該被option api限制思維,而更多關(guān)注邏輯內(nèi)聚問題
3: 關(guān)于 setup 中沒有 this 的問題
vue 官方文檔是這么解釋的:在 setup() 內(nèi)部,this 不會是該活躍實(shí)例的引用,因?yàn)?setup() 是在解析其它組件選項(xiàng)之前被調(diào)用的,所以 setup() 內(nèi)部的 this 的行為與其它選項(xiàng)中的 this 完全不同。這在和其它選項(xiàng)式 API 一起使用 setup() 時(shí)可能會導(dǎo)致混淆。這意味著,除了 props 之外,你將無法訪問組件中聲明的任何屬性---本地狀態(tài),計(jì)算屬性/方法。
但是從源碼實(shí)現(xiàn)你會發(fā)現(xiàn)其實(shí)組件實(shí)例創(chuàng)建在前,函數(shù)之所以訪問不到 this,是因?yàn)樗趫?zhí)行 setup 函數(shù)的時(shí)候,就沒有把組件實(shí)例 instance 傳給 setup。也沒有把 this 指向?qū)嵗?instance。So 執(zhí)行順序其實(shí)是:組件實(shí)例創(chuàng)建在 setup 函數(shù)執(zhí)行之前,但是 setup 執(zhí)行的時(shí)候,組件還沒有 mounted,而晚于 beforeCreate 鉤子,早于 create 鉤子。
4: reactive VS ref
剛開始看文檔時(shí),大家往往會去拿這兩個(gè)去對比,總結(jié)一下:
reactive API: 可以把一個(gè)對象數(shù)據(jù)變成響應(yīng)式(等同于 2.x 中的 Vue.observable()),Composition API 更推薦用戶主動定義響應(yīng)式式數(shù)據(jù),而非內(nèi)部的黑盒處理
ref: 針對數(shù)組 or 對象本質(zhì)就是reactive實(shí)現(xiàn)的,讀取值時(shí)是ref.value
另外注意一下toRefs: 針對組合函數(shù)返回響應(yīng)式對對象時(shí)使用 toRefs, 本質(zhì)上是幫我們做了一層getter和setter處理,解構(gòu)就可以得到響應(yīng)式的數(shù)據(jù),這也就降低了一些關(guān)于ref的心智負(fù)擔(dān)
5: Vue3 響應(yīng)式比 Vue2 的性能要好嗎?
vue3 出來的時(shí)候,往往聽到的一些答案都是說 Vue3 性能比 Vue2 性能好,但真的是嗎?在 Vue3 發(fā)布那一段期間中(我也去薅羊毛薅到了 1 元的源碼課解析中學(xué)習(xí)了一番:老黃 YYDS),甚至包括群里大家都在討論這個(gè)問題。
首先從實(shí)現(xiàn)上來講:我們都知道 vue2 中的響應(yīng)式主要?dú)w功于Object.defineProperty, 它主要劫持對象的屬性,所以它不能觀測到對象屬性的添加和刪除,而在 vue 中,是用Proxy實(shí)現(xiàn)的,劫持的是整個(gè)對象,能規(guī)避掉 vue2 留下的問題,但也有明顯的缺點(diǎn)就是兼容性不夠強(qiáng)。但是對比 Vue2,你需要知道的是 vue3 性能上的優(yōu)勢主要還是體現(xiàn)在初始化階段。因?yàn)?Vue2 中定位響應(yīng)式對象時(shí),會遞歸把子對象變成響應(yīng)式。而 Vue3 其實(shí)是惰性執(zhí)行:在對象屬性被真正訪問的時(shí)候才會遞歸執(zhí)行子對象變成響應(yīng)式。
6: Vue Composition API VS React Hooks
Vue3 的Composition API和React Hooks的寫法很像,大家都會忍不住拿他們?nèi)プ鰝€(gè)對比,關(guān)于這部分內(nèi)容的 PK,我司的小伙伴已經(jīng)給總結(jié)過了,還很全面,這個(gè)就不細(xì)說了,傳送門:
Vue Composition API 和 React Hooks 對比:https://juejin.cn/post/6847902223918170126
除了一些常見的問題時(shí),更重要的就是實(shí)踐,對于新項(xiàng)目,可以直接使用 vue3 起步,但更多的對于已有的項(xiàng)目,在 vue2 升級到 vue3 實(shí)踐時(shí),肯定會踩不少坑,以下是關(guān)于在實(shí)踐過程中可能會遇到的一些注意點(diǎn)&坑點(diǎn)
1. 報(bào)錯(cuò)以下警告:告知 script setup 當(dāng)前仍然是個(gè)實(shí)驗(yàn)性的新特性,還沒有作為正式特性發(fā)布,后面會不會有變化還不好說。
- [@vue/compiler-sfc] <script setup> is still an experimental proposal.
- Follow its status at https://github.com/vuejs/rfcs/pull/227.
- [@vue/compiler-sfc] When using experimental features,
- it is recommended to pin your vue dependencies to exact versions to avoid breakage.
- [@vue/compiler-sfc] `defineProps` is a compiler macro and no longer needs to be imported.
2: 遷移 vue3 時(shí),setup 中只保留了不再有once, $off 等方法,只保留了 emit,如下:
- setup(props, { emit }) {
- const rootRef = ref(null)
- const scroll = useScrolll(rootRef, props, emit)
- return {
- rootRef,
- scroll
- }
- }
- // scroll.js 中
- scrollVal.on('scroll', pos => {
- emit('scroll', pos)
- })
3: 關(guān)于 computed: 3.X 把 computed 變成了一個(gè)計(jì)算屬性 API,所以可以有多個(gè) computed,可以沿用 Vue.js 2.x 的使用方法
- // vue2.x
- computed: {
- loading() {
- return !this.list.length
- }
- },
- // vue3.x
- const loading = computed(() => !this.list.length)
- const titleList = computed(() => {
- return props.data.map((item) => item.title)
- })
4: 關(guān)于 watch:對于監(jiān)聽對象是分隔字符串時(shí),需要在選項(xiàng)參數(shù)中指定 deep: true
- // vue2.x
- watch: {
- 'data.distance': function (newVal, oldVal) {
- if (newVal === constants.DISTANCE_ON) {
- ...
- }
- },
- },
- // vue3.x
- watch(
- () => this.data.distance,
- (newVal, oldVal) => {
- if (newVal === constants.DISTANCE_ON) {
- ...
- }
- },
- { deep: true },
- )
5: 在 Vue3 中組件沒有filters選項(xiàng),遷移過程中,可以用computed/methods替代
- // vue2.x
- filters: {
- // just a method
- dateFormat,
- },
- // vue3.x
- const dateFormat = computed(() => {
- // just a method
- dateFormat,
- })
可以在同一個(gè)組件上使用多個(gè) 進(jìn)行雙向綁定,可以使用自定義 v-model 修飾符
6: vue3.X 中去掉了.sync,用v-model代替 并且同一個(gè)組件中不僅限于只有一個(gè)v-model
- // vue2.x
- <basic-info-dialog :shown.sync="dialogFormVisible">
- <ChildComponent v-bind:name.sync="name" />
- // vue3.x
- <basic-info-dialog v-model:shown="dialogFormVisible">
總結(jié)
踩坑還在繼續(xù),繼續(xù)實(shí)踐繼續(xù)踩!
參考資料
vue 文檔:https://vue3js.cn/docs/zh/guide/composition-api-setup.html#%E4%BD%BF%E7%94%A8%E6%B8%B2%E6%9F%93%E5%87%BD%E6%95%B0
Vue Composition API 和 React Hooks 對比:https://juejin.cn/post/6847902223918170126
前往微醫(yī)互聯(lián)網(wǎng)醫(yī)院在線診療平臺,快速問診,3分鐘為你找到三甲醫(yī)生。(https://wy.guahao.com/?channel=influence)