溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Vue面試題及答案有哪些

發(fā)布時(shí)間:2023-01-04 09:06:08 來源:億速云 閱讀:126 作者:iii 欄目:編程語言

這篇文章主要介紹了Vue面試題及答案有哪些的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Vue面試題及答案有哪些文章都會(huì)有所收獲,下面我們一起來看看吧。

1. 簡述 Vue 生命周期

答題思路:

  • Vue 生命周期是什么?

  • Vue 生命周期有哪些階段?

  • Vue 生命周期的流程?

  • 結(jié)合實(shí)踐

  • 擴(kuò)展:在 Vue3 變化 Vue 生命周期的變化 

回答范例:

  • 生命周期這個(gè)詞應(yīng)該是很好理解的,在我們生活中就會(huì)常常碰到,比如談到一個(gè)人的生命周期,我們會(huì)說人這一生會(huì)經(jīng)歷嬰兒、兒童、少年、青年、中年、老年這幾個(gè)階段。 而 Vue 的生命周期也是如此,在 Vue 中的每個(gè)組件都會(huì)經(jīng)歷從創(chuàng)建掛載更新再到銷毀這幾個(gè)階段,而在這些階段中,Vue 會(huì)運(yùn)行一種叫做生命周期鉤子的函數(shù),方便我們?cè)谔囟ǖ碾A段有機(jī)會(huì)添加上我們自己的代碼。

  • Vue 生命周期總共可以分為 8 各階段:創(chuàng)建前后掛載前后、更新前后、銷毀前后,以及一些特殊場景的生命周期(keep-alive 激活時(shí)、捕獲后代組件錯(cuò)誤時(shí))。Vue3 中還新增了三個(gè)用于調(diào)試和服務(wù)端渲染場景。

  • 這幾個(gè)階段對(duì)應(yīng)的鉤子函數(shù) API依次為:beforeCreate create beforeMount mounted beforeUpdate updated activated(keep-alive 激活時(shí)調(diào)用) deactivated(keep-alive 停用時(shí)調(diào)用) beforeDestory destoryed errorCaptured(捕獲子孫組件錯(cuò)誤時(shí)調(diào)用)。

    在 Vue3 中的變化 絕大多數(shù)只要加上前綴 on 即可,比如 mounted 變?yōu)?onMounted,除了 beforeDestroydestroyed 被重新命名為 beforeUnmountunMounted(這樣與前面的 beforeMountmounted 對(duì)應(yīng),強(qiáng)迫癥表示很贊?)

  • beforeCreate 在組件創(chuàng)建前調(diào)用,通常用于插件開發(fā)中執(zhí)行一些初始化任務(wù);created 組件創(chuàng)建完畢調(diào)用,可以訪問各種數(shù)據(jù),請(qǐng)求接口數(shù)據(jù)等;mounted 組件掛載時(shí)調(diào)用 可以訪問數(shù)據(jù)、dom 元素、子組件等;beforeUpdate 更新前調(diào)用 此時(shí) view 層還未更新,可用于獲取更新前的各種狀態(tài);updated 完成更新時(shí)調(diào)用 此時(shí)view層已經(jīng)完成更新,所有狀態(tài)已經(jīng)是最新的了;beforeUnmount 實(shí)例被銷毀前調(diào)用,可用于一些定時(shí)器或訂閱的取消;unMounted 銷毀一個(gè)實(shí)例時(shí)調(diào)用 可以清理與其他實(shí)例的鏈接,解綁它的全部指令以及事件監(jiān)聽器。

  • 在 Vue3 中: setup 是比 created 先執(zhí)行的而且沒有 beforeCreate 和  created。

2. Vue 中如何做權(quán)限管理

  • 權(quán)限管理一般需求就是對(duì)頁面權(quán)限和按鈕權(quán)限的管理

  • 具體實(shí)現(xiàn)的時(shí)候分前端實(shí)現(xiàn)和后端實(shí)現(xiàn)兩種方案: 前端方案會(huì)把所有路由信息在前端配置,通過路由守衛(wèi)要求用戶登錄,用戶登錄后根據(jù)角色過濾出路由表,然后在動(dòng)態(tài)添加路由。比如我會(huì)配置一個(gè) asyncRoutes 數(shù)組,需要認(rèn)證的頁面在路由的 meta 中添加一個(gè) roles 字段,等獲取用戶角色之后取兩者的交集,若結(jié)果不為空則說明可以訪問。過濾結(jié)束后剩下的路由就是用戶能訪問的頁面,最后通過 router.addRoutes(accessRoutes) 方式動(dòng)態(tài)添加路由即可。

    后端方案會(huì)把所有頁面路由信息存在數(shù)據(jù)庫中,用戶登錄的時(shí)候根據(jù)其角色查詢得到其能訪問的所有路由信息返回給前端,前端再通過 addRoute 動(dòng)態(tài)添加路由信息。

    按鈕權(quán)限的控制通常會(huì)實(shí)現(xiàn)一個(gè)指令,例如 v-permission,將按鈕要求角色通過值傳給 v-permission 指令,在指令的 mounted 鉤子中可以判斷當(dāng)前用戶角色和按鈕是否存在交集,有就保留按鈕,沒有就移除按鈕。

  • 純前端方案的優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,不需要額外權(quán)限管理頁面,但是維護(hù)起來問題比較大,有新的頁面和角色需求就要修改前端代碼和重新打包部署服務(wù)端方案就不存在這個(gè)問題,通過專門的角色和權(quán)限管理頁面,配置頁面和按鈕權(quán)限信息到數(shù)據(jù)庫,應(yīng)用每次登陸時(shí)獲取的都是最新的路由信息。

自己的話:權(quán)限管理一般分頁面權(quán)限和按鈕權(quán)限,而具體實(shí)現(xiàn)方案又分前端實(shí)現(xiàn)和后端實(shí)現(xiàn),前端實(shí)現(xiàn)就是會(huì)在前端維護(hù)一份動(dòng)態(tài)的路由數(shù)組,通過用戶登錄后的角色來篩選它所擁有權(quán)限的頁面,最后通過 addRoute 將動(dòng)態(tài)添加到 router 中;而后端實(shí)現(xiàn)的不同點(diǎn)就是這些路由是后端返回給前端,前端再動(dòng)態(tài)添加進(jìn)去的。 按鈕權(quán)限一般會(huì)實(shí)現(xiàn)一個(gè) v-permission ,通過判斷用戶有沒有權(quán)限來控制按鈕是否顯示。 純前端方案的優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,但是維護(hù)問題大,有新的頁面和角色需求都需要改代碼重新打包部署,服務(wù)端則不存在這個(gè)問題。

3. Vue 中雙向綁定的使用和原理

回答思路:

  • 什么是雙向綁定?

  • 雙向綁定的好處?

  • 在什么地方使用雙向綁定?

  • 雙向綁定的使用方式、使用細(xì)節(jié)、Vue3中的變化

  • 原理實(shí)現(xiàn)描述

回答:

  • Vue中的雙向綁定是一個(gè)指令 v-model ,它可以綁定一個(gè)響應(yīng)式數(shù)據(jù)到視圖,同時(shí)視圖中變化也能改變?cè)撝怠?/p>

  • v-model 是一個(gè)語法糖,它的原理(默認(rèn)請(qǐng)情況下)就是通過 :value 將變量掛到 dom 上,再通過 input事件 監(jiān)聽 dom 的變化改變變量的值。使用 v-model的好處就是方便呀,減少了大量的繁瑣的事件處理,提高開發(fā)效率。

  • 通常在表單上使用 v-model,還可以在自定義組件上使用,表示某個(gè)值得輸入和輸出控制。

  • 可以結(jié)合修飾符做進(jìn)一步限定(lazy/number/trim),用在自定義組件上時(shí)有些不同,它相當(dāng)于是給了子組件一個(gè) modelValue 的 屬性 和 update:modelValue 的 事件; 在 Vue3 中還可以用參數(shù)形式指定多個(gè)不同的綁定,如 v-model:foo 這個(gè)時(shí)候就相當(dāng)于 給了子組件一個(gè) foo 的 屬性 和 update:foo 的事件。

  • v-model作為一個(gè)指令,它的原理就是 Vue 編譯器會(huì)把它轉(zhuǎn)換成 value屬性綁定和input的監(jiān)聽事件,上面說過是默認(rèn)情況下,實(shí)際上編譯器會(huì)根據(jù)表單元素的不同分配不同的事件,比如 checkboxradio 類型的input 會(huì)轉(zhuǎn)換為 checkedchange 事件。

4. Vue 組件之間通信有哪些?

Vue 組件之間通信有以下這么幾種:

  • props

  • $emit$on、$off、$once(后三者在Vue3中已被廢除)

  • $children(Vue3中廢除)$parent

  • $attrs、$listeners(Vue3中廢除)

  • ref

  • $root

  • eventbus (Vue3中不好使了,需要自己封裝)

  • vuex、pinia

  • provide + inject

以上的方法長按使用場景可以分為:

  • 父子組件之間可以使用

    props /$emit/ $parent/ ref /$attrs

  • 兄弟組件之間可以使用

    $parent / $root/ eventbus / vuex

  • 跨層及組件之間可以使用

    eventbus / vuex pinia / provide + inject

5.你了解哪些 Vue 性能優(yōu)化方法?

  • 路由懶加載:有效拆分 App 尺寸,訪問時(shí)才異步加載

const router = createRouter({
    routes: [
        { path : '/foo', component: () => import('./foo.vue)}
    ]
})

  • keep-alive 緩存頁面:避免重復(fù)創(chuàng)建組件實(shí)例,且能保存緩存組件狀態(tài)

<keep-alive>
  <router-view v-if="$route.meta.keepAlive == true"></router-view>
</keep-alive>
<router-view v-if="$route.meta.keepAlive != true"></router-view>

  • 使用 v-show 復(fù)用 DOM:避免重復(fù)創(chuàng)建組件

  • v-for 遍歷避免同時(shí)使用 v-if(實(shí)際上這在 Vue3 中是錯(cuò)誤的寫法)

  • v-oncev-memo: 不再變化的數(shù)據(jù)使用 v-once;按條件跳過更新時(shí)使用 v-memo

  • 長列表性能優(yōu)化:如果是大數(shù)據(jù)長列表,可采用虛擬滾動(dòng),只渲染少部分區(qū)域的內(nèi)容。一些開源庫(vue-virtual-scroller / vue-virtual-scroll-grid

  • 事件的銷毀:Vue組件銷毀時(shí),會(huì)自動(dòng)解綁它的全部指令以及事件監(jiān)聽器,但是僅限于組件本身的事件。

  • 圖片懶加載,自定義 v-lazy 指令 (參考項(xiàng)目:vue-lazyload

  • 第三方插件按需引入 element-plus 避免體積太大

  • 子組件分割策略:較重的狀態(tài)組件適合拆分

  • SSR 服務(wù)端渲染 解決首屏渲染慢的問題

6. 刷新后 Vuex 狀態(tài)丟失怎么解決?

思路:

  • 刷新后 Vuex 狀態(tài)為什么會(huì)丟失?

  • 解決方法

  • 第三方庫以及原理探討

  • 個(gè)人理解

回答:

  • 因?yàn)?Vuex 只是在內(nèi)存中保存狀態(tài),刷新后就會(huì)丟失,如果要持久化就要存起來。

  • 可以是用 localStorage 存儲(chǔ) Vuex 的狀態(tài),store 中把值取出來作為 state 的初始值,提交 mutation 的時(shí)候就存入 localStorage

  • 可以用 vuex-persist、vuex-persistedstate 這種插件,可以通過插件選項(xiàng)控制哪些需要持久化。內(nèi)部的原理就是通過訂閱 mutation 變化做統(tǒng)一處理。

  • 這里有兩個(gè)問題,一是如果用戶手動(dòng)改了 localStorage怎么辦?那我 Vuex 里的狀態(tài)不是也改變了?二是由于 localStorage API 的原因只能存儲(chǔ)字符串,所以我們只能將數(shù)據(jù)通過 JSON.stringify 轉(zhuǎn)換為字符串,而當(dāng)我們存儲(chǔ)的數(shù)據(jù)為 Map、Set、Function 這種引用類型的數(shù)據(jù)時(shí),JSON.stringify 轉(zhuǎn)換后會(huì)變味 {} 而丟失。

對(duì)應(yīng)第一個(gè)問題我的解決方法是可以通過 監(jiān)聽 storage 事件來清除數(shù)據(jù)

window.addEventListener("storage", function () {
    localStorage.clear();
    window.location.href = '/login'
    console.error("不要修改localStorage的值~~~");
});

對(duì)于第二個(gè)問題沒辦法了,只能選擇不適用 MapSet 這種引用類型。

7. Vue3 為什么用 Proxy 替代 defineProperty ?

思路:

  • 屬性攔截的幾種方式

  • defineProperty的問題

  • Proxy的優(yōu)點(diǎn)

  • 其他考量

回答:

  • JS 中做屬性攔截常見的方式有三種:defineProperty、getter/settersProxy

  • Vue2 中使用 defineProperty 的原因是, 2013 年只能使用這種方式,由于該 API 存在一些局限性,比如對(duì)于數(shù)組的攔截有問題,為此 Vue 需要專門為數(shù)組響應(yīng)式做一套實(shí)現(xiàn)。另外不能攔截那些新增、刪除屬性;最后 defineProperty 方案在初始化時(shí)需要深度遞歸遍歷處理對(duì)象才能對(duì)它進(jìn)行完全攔截,明顯增加了初始化的時(shí)間。

  • 以上兩點(diǎn)在 Proxy 出現(xiàn)后迎刃而解,不僅可以對(duì)數(shù)組實(shí)現(xiàn)攔截,還能對(duì) MapSet 實(shí)現(xiàn)攔截;另外 Proxy 的攔截也是懶處理行為,如果用戶沒有訪問嵌套對(duì)象,那么也不會(huì)實(shí)施攔截,這就讓初始化的速度和內(nèi)存占用改善了。

  • Proxy 有兼容性問題,完全不支持IE

8. 怎么實(shí)現(xiàn)路由懶加載?

思路:

  • 必要性

  • 何時(shí)用

  • 怎么用

  • 使用細(xì)節(jié)

回答:

  • 當(dāng)打包構(gòu)建時(shí),Javascript 抱回變得非常大,影響頁面加載。利用路由懶加載我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)最賤,這樣更加高效,是一種優(yōu)化手段。

  • 一般來說,對(duì)于所有的路由都使用動(dòng)態(tài)導(dǎo)入是個(gè)好主意

  • component 選項(xiàng)配置一個(gè)返回 Promise組件的函數(shù)就可以定義懶加載路由.例如:

{
  path: '/login',
  component: () => import('../views/login/Login.vue')
},

  • 結(jié)合注釋

{
  path: '/login',
  component: () => import(/* webpackChunkName: "login" */'../views/login/Login.vue')
},

vite中結(jié)合rollupOptions定義分塊 5. 路由中不能使用異步組件

9. history模式 和 hash 模式有何區(qū)別?

  • Vue-Router 有三個(gè)模式,其中 history 和 hash 更為常用。兩者差別主要在顯示形式和部署上,

  • hash模式在地址欄現(xiàn)實(shí)的時(shí)候有一個(gè) #,這種方式使用和部署都較簡單;history模式url看起來更優(yōu)雅沒關(guān),但是應(yīng)用在部署時(shí)需要做特殊配置,web服務(wù)器需要做回退處理,否則會(huì)出現(xiàn)刷新頁面404的問題。

  • 在實(shí)現(xiàn)上 hash模式是監(jiān)聽hashchange事件觸發(fā)路由跳轉(zhuǎn),history模式是監(jiān)聽popstate 事件觸發(fā)路由跳轉(zhuǎn)。

10. 說說 nextTick 的使用和原理?

  • VuenextTick 是等待下一次 DOM 更新刷新的工具方法。

  • Vue 有一個(gè)異步更新策略,意思是如果數(shù)據(jù)變化,Vue 不會(huì)立刻更新 DOM,而是開啟一個(gè)隊(duì)列,把組件更新函數(shù)保存在隊(duì)列中,在同一時(shí)間循環(huán)中發(fā)生的所有數(shù)據(jù)變更會(huì)異步的批量更新。這一策略導(dǎo)致我們對(duì)數(shù)據(jù)的修改不會(huì)立刻體現(xiàn)在 DOM 上,此時(shí)如果想要獲取更新后的 DOM 狀態(tài),就需要使用 nextTicknextTick 接受一個(gè)函數(shù),我們可以在這個(gè)函數(shù)內(nèi)部訪問最新的 DOM 狀態(tài) 在開發(fā)時(shí),有兩個(gè)場景我們會(huì)用到 nextTick

    • created 中想要獲取 DOM;

    • 響應(yīng)式數(shù)據(jù)變化后獲取 DOM 更新后的狀態(tài);

  • nextTick 的原理:在 Vue 內(nèi)部,nextTick 之所以能夠讓我們看到 DOM 更新后的結(jié)果,是因?yàn)槲覀儌魅氲?callback 會(huì)被添加到隊(duì)列刷新函數(shù)的后面,這樣等隊(duì)列內(nèi)部的更新函數(shù)都執(zhí)行完畢,所有 DOM 操作也就結(jié)束了,callback 自然能夠獲取最新的 DOM 值。

11. v-for 和 v-if 優(yōu)先級(jí)

先回答答案:vue2 中, v-for 的優(yōu)先級(jí)更高 但是在 vue3 中, v-if 的優(yōu)先級(jí)更高

拓展:無論什么時(shí)候,我們都不應(yīng)該把 v-forv-if 放在一起, 怎么解決呢?一是可以定義一個(gè)計(jì)算屬性,讓 v-for 遍歷計(jì)算屬性。二是可以把 if 移到內(nèi)部容器里(ul ol)或者把v-for移植外部容器(template)中

vue2文檔vue3文檔

12. 如何監(jiān)聽 Vuex 狀態(tài)變化?

  • watch

  • store.subscribe()

watch 方式,可以以字符串形式監(jiān)聽 $store.state.xx; subscribe 方法參數(shù)是一個(gè)回調(diào)函數(shù),回調(diào)函數(shù)接受mutation 對(duì)象和 state 對(duì)象,可以通過 mutation.type 判斷監(jiān)聽的目標(biāo)。 wtach 方法更簡單好用, subscribe 會(huì)略繁瑣,一般用 vuex 插件中(可以提一下vuex的持久化插件vuex-persist、vuex-persistedstate

13. 你覺得 Vuex 有什么缺點(diǎn)?

  • 不支持持久化,頁面刷新狀態(tài)就會(huì)丟失

  • 使用模塊比較繁瑣

  • 不支持 ts (或者說很不友好)

vue3 + pinia 會(huì)是更好的組合。

14. ref 和 reactive 異同點(diǎn)?

  • 兩者都能返回響應(yīng)式對(duì)象,ref 返回的是一個(gè)響應(yīng)式Ref 對(duì)象, reactive 返回的是響應(yīng)式代理對(duì)象。

  • ref 通常是處理單值得響應(yīng)式,reactive 用于處理對(duì)象類型的數(shù)據(jù)響應(yīng)式

  • ref 需要通過 .value 訪問, 在視圖中會(huì)自動(dòng)脫 ref,不需要 .value,ref 可以接收對(duì)象或數(shù)組但內(nèi)部依然是 reactive 實(shí)現(xiàn)的;reactive 如果接收 Ref 對(duì)象會(huì)自動(dòng)脫 ref ;使用展開運(yùn)算符展開 reactive 返回的響應(yīng)式對(duì)象會(huì)使其失去響應(yīng)性,可以結(jié)合 toRefs()將值轉(zhuǎn)換為 Ref 對(duì)象后再展開。

  • reactive 內(nèi)部使用 Prxoy 代理攔截對(duì)象各種操作,而 ref 內(nèi)部封裝一個(gè) RefImpl 類,設(shè)置 get value/set value,攔截用戶對(duì)值得訪問。

16. Vue 中如何擴(kuò)展一個(gè)組件?

  • 邏輯擴(kuò)展:mixins、extendscomposition api:

  • 內(nèi)容擴(kuò)展:slots

mixins 很靈活,但是會(huì)沖突很混亂。extends 是一個(gè)不太常用的選項(xiàng),更 mixins 的不同是它只能擴(kuò)展單個(gè)對(duì)象,優(yōu)先級(jí)比 mixins 高。

混入的數(shù)據(jù)和方法 不能明確判斷來源 而且可能和當(dāng)前組件內(nèi)變量 產(chǎn)生命名沖突,composition api 可以很好解決這些問題,利用獨(dú)立出來的響應(yīng)式模塊可以很方便的編寫?yīng)毩⑦壿嫴⑻峁╉憫?yīng)式數(shù)據(jù)局,增強(qiáng)代碼的可讀性和維護(hù)性。

擴(kuò)展:Vue.mixin(全局混入)  Vue.extend(有點(diǎn)像是 類/組件的繼承 創(chuàng)建一個(gè)子類)

17. vue-loader 是什么?

  • vue-loader 是用于處理單文件組件(SFC)的webpack loader

  • 因?yàn)橛辛?vue-loader,我們才能用 .vue 文件形式編寫代碼,將代碼分割為 template script style

  • webpack 在打包的時(shí)候,會(huì)以 loader 的方式調(diào)用 vue-loader

  • vue-loader 被執(zhí)行時(shí),它會(huì)對(duì) SFC 中的每個(gè)語言塊用單獨(dú)的 loader 鏈處理,最后將這些單獨(dú)的塊裝配成最終的組件模塊

18. 子組件能否修改父組件數(shù)據(jù)

不能直接改。

組件化開發(fā)中有一個(gè)單向數(shù)據(jù)流原則,不在子組件修改父組件數(shù)據(jù)是個(gè)常識(shí)

如果你確實(shí)需要改,請(qǐng)通過emit向父組件發(fā)送一個(gè)事件,在父組件中修改

19. 怎么定義動(dòng)態(tài)路由,怎么獲取傳過來的動(dòng)態(tài)參數(shù)?

我么可以在路徑中使用一個(gè)動(dòng)態(tài)字段來實(shí)現(xiàn),例如/users/:id 其中 :id 就是路徑參數(shù)。 可以通過 this.$route.parmas獲取,參數(shù)還可以有多個(gè), $route 對(duì)象還公開了其他有用的信息如 query hash等。

20. 說說對(duì) Vue 數(shù)據(jù)響應(yīng)式的理解

思路:

  • 什么是響應(yīng)式?

  • 為什么vue需要響應(yīng)式?

  • 有什么好處?

  • vue的響應(yīng)式怎么實(shí)現(xiàn)的,有哪些優(yōu)缺點(diǎn)?

  • vue3中的響應(yīng)式的新變化

回答:

  • 數(shù)據(jù)響應(yīng)式就是 能夠監(jiān)測到數(shù)據(jù)變化并且做出響應(yīng)的一種機(jī)制

  • vue 中要解決的一個(gè)核心問題就是連接數(shù)據(jù)層和視圖層,通過數(shù)據(jù)變化驅(qū)動(dòng)視圖更新,要做到這點(diǎn)就需要對(duì)數(shù)據(jù)做響應(yīng)式處理。

  • 通過數(shù)據(jù)響應(yīng)式加上虛擬 DOMpatch 算法,我們只需要操作數(shù)據(jù),關(guān)心業(yè)務(wù),完全不需要接觸繁瑣的 DOM 操作,打打提升了開發(fā)效率,降低開發(fā)難度。

  • vue2 中實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式的核心就是通過 Object.defineProperty() 方法對(duì)數(shù)據(jù)進(jìn)行攔截,當(dāng) get 數(shù)據(jù)時(shí)做依賴收集 set 數(shù)據(jù)時(shí)做更新通知。這種機(jī)制很好的及絕了數(shù)據(jù)響應(yīng)式的問題,但是實(shí)際使用也存在缺點(diǎn),比如在初始化時(shí)的遞歸遍歷會(huì)造成性能損失;無法監(jiān)聽新增或刪除屬性,在 vue 中要通過像 Vue.set/delete 這種特定的 API 才能實(shí)現(xiàn)對(duì)對(duì)象數(shù)組屬性的添加和刪除,而且也不支持 Ma、Set這些數(shù)據(jù)結(jié)構(gòu),

  • 為了解決這些問題,Vue3 重寫了這部分實(shí)現(xiàn),利用的是 ES6 中的 Proxy 代理要響應(yīng)化的數(shù)據(jù)。它有很多好處,初始化性能和內(nèi)存都大幅改善,也不需要特殊的 API ,但是不支持 IE 瀏覽器。

21. 從 template 到 render 做了什么

templaterender 的過程其實(shí)是問的 vue 編譯器 工作原理。

思路:

  • 引入編譯器概念

  • 說明編譯器的必要性

  • 闡述編譯器工作流程

回答:

  • Vue 中有個(gè)獨(dú)特的編譯模塊,稱為 compiler,它的主要作用是將 template 編譯為 js 可執(zhí)行的 render 函數(shù)

  • 之所以需要這個(gè)編譯過程是為了便于我們高校的編寫試圖模版。相比而言,我們還是更愿意用 HTML來編寫視圖,直觀且高效。手寫 render 函數(shù)不僅效率低下,而且失去了被編譯器的優(yōu)化能力。

  • Vue 編譯器 首先會(huì)對(duì) template進(jìn)行解析Parse ),結(jié)束后會(huì)得到一個(gè)抽象語法樹AST,然后對(duì) AST 進(jìn)行深加工轉(zhuǎn)換(transform),最后將得到的 AST 生成為 js 代碼,也就是 render 函數(shù)

22. 如何緩存和更新組件

  • 緩存組件可以使用 keep-alive 組件,include 和 exclude 可以指定包含不包含哪些組件。

  • Vue3 結(jié)合 vue-router 使用變化非常大,之前是 keep-alive 包含 router-view,現(xiàn)在是 router-view 包含 keep-alive

  • 緩存后如果想要獲取數(shù)據(jù)可以使用 actived 鉤子 或者 beforeRouteEntervue-router 的一個(gè)守衛(wèi))

  • keep-alive 是一個(gè)通用組件,它內(nèi)部定義了一個(gè) map,緩存創(chuàng)建過的組件實(shí)例,它返回的渲染函數(shù)內(nèi)部會(huì)查找內(nèi)嵌的 component 組件對(duì)應(yīng)組件的 vnode,如果改組件在map中存在就直接返回它。由于 componentis 屬性是一個(gè)響應(yīng)式數(shù)據(jù),因此只要它變化,keep-aliverender 函數(shù)就會(huì)重新執(zhí)行。

23. 虛擬DOM

  • 虛擬 DOM 是什么? 虛擬 DOM 的本質(zhì)就是一個(gè) Javascript 對(duì)象。

  • 為什么要引入虛擬 DOM?(好處) 它能有效減少操作 DOM 的次數(shù),方便實(shí)現(xiàn)跨平臺(tái)

  • 虛擬DOM如何生成?compiler 編譯器會(huì)把 template 模版編譯成渲染函數(shù),接下來在 mount 掛載的過程會(huì)調(diào)用這個(gè)渲染函數(shù),返回的對(duì)象就是 虛擬DOM 。掛載結(jié)束后,會(huì)進(jìn)入更新流程。如果某些響應(yīng)式數(shù)據(jù)發(fā)生變化,將會(huì)引起組件重新 render,此時(shí)會(huì)生成新的 虛擬DOM,和上次渲染結(jié)果做 diff 操作,最小量的操作 dom,從而高效更新視圖。

24. 什么是異步組件

  • 異步組件就是不會(huì)立即加載而是會(huì)在需要的時(shí)候加載的組件。在大型應(yīng)用中,我們需要分割代碼為更小的塊試就可以用異步組件。

  • 不僅可以在路由切換時(shí)懶加載組件,還可以在組件中使用異步組件,從而更細(xì)的分割代碼。

  • 使用異步組件最簡單的方式是直接給 defineAsyncComponet 指定一個(gè) loader 函數(shù),結(jié)合 ES 模塊 動(dòng)態(tài)導(dǎo)入函數(shù) import 可以快速實(shí)現(xiàn)。Vue3 還可以結(jié)合 Suspense 組件使用異步組件。

  • 異步組件容易和路由懶加載混淆,實(shí)際上不是一個(gè)東西。異步組件不能被用于定義懶加載路由上,處理它的是 Vue 框架,處理路由組件加載的是 vue-router。但是可以在懶加載的路由組件中使用異步組件。

25. 說說Vue長列表優(yōu)化思路

  • 避免大數(shù)據(jù)量:可以采用分頁的方式獲取

  • 避免渲染大量數(shù)據(jù):vue-virtual-scroller等虛擬滾動(dòng)方案,只渲染視口范圍內(nèi)的數(shù)據(jù)

  • 避免更新:可以使用v-once方式只渲染一次

  • 優(yōu)化更新:通過v-memo緩存組數(shù),有條件更新,提高服用,避免不必要更新

  • 按需加載數(shù)據(jù):可以采用 懶加載 方式,在用戶需要的時(shí)候在加載數(shù)據(jù)。

26. computed & watch

  • computed 是計(jì)算屬性,watch 是偵聽器。

  • computed 通常用于處理模版中復(fù)雜的邏輯,而 watch 通常用于需要監(jiān)聽一個(gè)響應(yīng)式對(duì)象的變化而做一些操作的時(shí)候

  • watch 可以進(jìn)行異步操作,computed 不行。

  • 計(jì)算屬性傳遞一個(gè)對(duì)象 有 setget 兩個(gè)選項(xiàng),是它稱為即可讀又可寫的計(jì)算屬性,如果傳遞的是函數(shù)的話默認(rèn)就是 get 選項(xiàng),watch 可以傳遞一個(gè)對(duì)象,設(shè)置deep、immediate等選項(xiàng)

  • vue3watch 發(fā)生了一些變化,例如不能再偵測一個(gè)點(diǎn)操符之外的字符串表達(dá)式,reactivity API 中新出的 watch、watchEffect 可以完全替代 watch 選項(xiàng),而且功能更加強(qiáng)大

27. SPA 和 SSR的區(qū)別是什么?

  • SPA(Single Page Application)是單頁面應(yīng)用。一般也稱為客戶端渲染,簡稱 CSR 。SSR(Server Side Render) 即服務(wù)端渲染。一般也稱為多頁面應(yīng)用(Mulpile Page Application),簡稱 MPA。

  • SPA 只會(huì)首次請(qǐng)求 html 文件,后續(xù)只需要請(qǐng)求 JSON 數(shù)據(jù)即可,因此用戶體驗(yàn)更好,節(jié)約流量,服務(wù)端壓力也較小。但是首屏加載的時(shí)間會(huì)變長,而且 SEO 不友好。為了解決以上缺點(diǎn),就有了 SSR 方案,由于 HTML 內(nèi)容在服務(wù)器一次性生成出來,首屏加載快,搜索引擎也可以很方便的抓取頁面信息。但同時(shí) SSR 方案也會(huì)有性能,開發(fā)受限等問題。

  • 選擇上,如果有首屏加載優(yōu)化需求,SEO需求時(shí),就可以考慮SSR。

  • 但并不是只有這一種替代方案,比如對(duì)一些不常變化的靜態(tài)網(wǎng)站,SSR反而浪費(fèi)資源,我們可以考慮預(yù)渲染的方案。另外 nuxt.js/next.js 中給我們提供了SSG靜態(tài)網(wǎng)站生成方案也是很好的靜態(tài)站點(diǎn)解決方案,結(jié)合一些CI手段,可以起到很好的優(yōu)化效果。

28. diff 算法

回答思路:

  • diff算法是干什么的?

  • 必要性

  • 何時(shí)執(zhí)行

  • 具體執(zhí)行方式

  • 拔高:說一下vue3中的優(yōu)化

回答:

  • Vue 中的 diff 算法稱為 patching 算法,虛擬DOM要想轉(zhuǎn)化為真實(shí)DOM就需要通過 patch 方法轉(zhuǎn)換。

  • 最初 Vue1.x 視圖中農(nóng)每個(gè)依賴均有更新函數(shù)對(duì)應(yīng),可以做到精確更新,因此不需要 虛擬DOMpatching 算法支持,但是這樣粒度過細(xì)導(dǎo)致 Vue1.x 無法承載較大應(yīng)用;Vue2.x 中為了降低 Watcher 粒度,每個(gè)組件只有一個(gè) Watcher 與之對(duì)應(yīng),此時(shí)就需要引入 patching 算法才能精確找到發(fā)生變化的地方并高效更新。

  • vuediff 執(zhí)行的時(shí)刻是組件內(nèi)響應(yīng)式數(shù)據(jù)變更觸發(fā)實(shí)例執(zhí)行其更新函數(shù)時(shí),更新函數(shù)會(huì)再次執(zhí)行 render函數(shù) 獲得最新的 虛擬DOM ,然后執(zhí)行 patch函數(shù),對(duì)比新舊虛擬DOM,將其轉(zhuǎn)化為對(duì)應(yīng)的 DOM 操作。

  • patch 過程是一個(gè)遞歸過程,遵循深度優(yōu)先、同層比較的策略;以 vue3patch 為例:

    • 新的子節(jié)點(diǎn)是文本,老的子節(jié)點(diǎn)是數(shù)組則清空,并設(shè)置文本;

    • 新的子節(jié)點(diǎn)是文本,老的子節(jié)點(diǎn)是文本則直接更新文本;

    • 新的子節(jié)點(diǎn)是數(shù)組,老的子節(jié)點(diǎn)是文本則清空文本,并創(chuàng)建新子節(jié)點(diǎn)數(shù)組中的子元素;

    • 新的子節(jié)點(diǎn)是數(shù)組,老的子節(jié)點(diǎn)也是數(shù)組,那么比較兩組子節(jié)點(diǎn),更新細(xì)節(jié)blabla

    • 首先判斷兩個(gè)節(jié)點(diǎn)是否為相同同類節(jié)點(diǎn),不同則刪除重新創(chuàng)建

    • 如果雙方都是文本則更新文本內(nèi)容

    • 如果雙方都是元素節(jié)點(diǎn)則遞歸更新子元素,同時(shí)更新元素屬性

    • 更新子節(jié)點(diǎn)時(shí)又分了幾種情況:

  • vue3 中引入的更新策略:編譯期優(yōu)化 patchFlagsblock

29. 如何從0到1架構(gòu)一個(gè)Vue項(xiàng)目,說說有哪些步驟,插件,目錄結(jié)構(gòu)怎么組織

  • 從 0 創(chuàng)建項(xiàng)目我大致會(huì)做以下事情:項(xiàng)目構(gòu)建、引入必要插件、代碼規(guī)范、提交規(guī)范、常用庫和組件

  • 目前vue3項(xiàng)目我會(huì)用vite或者create-vue創(chuàng)建項(xiàng)目

  • 接下來引入必要插件:vue-router、vuex/pinia、element-plus、antd-vue、axios等等

  • 其他常用的庫有 像lodash、dayjs、nprogress等等..

  • 下面是代碼規(guī)范: editorconfig、prettier、eslint

  • 最后是提交規(guī)范,可以使用husky、Commitizen

  • 目錄結(jié)構(gòu)我喜歡按照下面的結(jié)構(gòu)來

+ |- /src
+   |- /assets 存放資源
+     |- /img   
+     |- /css   
+     |- /font   
+     |- /data   
+   |- base-ui  存放多個(gè)項(xiàng)目中都會(huì)用到的公共組件
+   |- components 存放這個(gè)項(xiàng)目用到的公共組件
+   |- hooks 存放自定義hook
+   |- views 視圖
+   |- store 狀態(tài)管理
+   |- router 路由
+   |- service 網(wǎng)絡(luò)請(qǐng)求
+   |- utils 工具
+   |- global 全局注冊(cè)、全局常量..

30. 你如何實(shí)現(xiàn)一個(gè)Vue-Router

一個(gè) SPA 應(yīng)用的路由需要解決的問題時(shí)頁面跳轉(zhuǎn)內(nèi)容改變同時(shí)不刷新,同時(shí)路由還需要已插件形式存在,所以:

  • 首先我會(huì)定義一個(gè) createRouter 函數(shù),返回路由器實(shí)例,實(shí)例內(nèi)部做幾件事;


    • 保存用戶傳入的配置項(xiàng)

    • 監(jiān)聽 hash 或者 popstate 事件

    • 回調(diào)里根據(jù) path 匹配對(duì)應(yīng)路由

  • router 定義成一個(gè) Vue 插件,即實(shí)現(xiàn) install 方法,內(nèi)部做兩件事:


    • 實(shí)現(xiàn)兩個(gè)全局組件:router-linkrouter-view,分別實(shí)現(xiàn)頁面跳轉(zhuǎn)和內(nèi)容顯示

    • 定義兩個(gè)全局變量:$router$route,組件內(nèi)可以訪問當(dāng)前路由和路由器實(shí)例

31. 什么情況需要使用Vuex模塊?

  • 在項(xiàng)目規(guī)模變大的之后,單獨(dú)一個(gè)store對(duì)象會(huì)過于龐大臃腫,此時(shí)通過模塊方式可以拆分來便于維護(hù)

  • 可以按之前規(guī)則單獨(dú)編寫資規(guī)模代碼,然后在主文件中通過 modules 選項(xiàng)組織起來:createStore({modules: {...}})

  • 使用時(shí)需要注意訪問子模塊狀態(tài)時(shí)需要加上注冊(cè)模塊名。但同時(shí)getters、mutationsactions又在全局空間中,使用方式和之前一樣。如果要做到完全拆分,需要在子模塊加上 namespace選項(xiàng),此時(shí)再訪問它們就要加上命名空間前綴。

  • 模塊的方式可以拆分代碼,但是缺點(diǎn)也很明顯,使用起來比較繁瑣,容易出錯(cuò),而且類型系統(tǒng)支持很差,不能給我們帶來幫助。pinia 顯然在這方面有了很大改進(jìn),是時(shí)候切換過去了。

32. vue 組件為什么只能有1個(gè)根節(jié)點(diǎn)

  • vue2 中組件確實(shí)只能有一個(gè)跟,但 vue3 中組件已經(jīng)可以多根組件了。

  • 之所以需要這樣是因?yàn)?vdom 是一顆單根樹形結(jié)構(gòu),patch 方法在遍歷的時(shí)候從根節(jié)點(diǎn)開始遍歷,它要求只有一個(gè)根節(jié)點(diǎn)。組件也會(huì)轉(zhuǎn)換為一個(gè) vdom,自然應(yīng)該滿足這個(gè)要求。

  • vue3 中之所以可以寫多個(gè)根節(jié)點(diǎn),是因?yàn)橐肓?Fragment 的概念,這是一個(gè)抽象的節(jié)點(diǎn),如果發(fā)現(xiàn)組件時(shí)多根的,就創(chuàng)建一個(gè) Fragment 節(jié)點(diǎn),把多個(gè)根節(jié)點(diǎn)作為它的 children。將來 pathch 的時(shí)候,如果發(fā)現(xiàn)是一個(gè) Fragment 節(jié)點(diǎn),則直接遍歷 children 創(chuàng)建或更新。

33. v-once 使用場景有哪些?

  • v-oncevue 的內(nèi)置指令,作用是僅渲染指定組件或元素一次,并跳過未來對(duì)其更新。

  • 如果我們有一些元素或者組件再初始化渲染之后不再需要變化,這種情況下適合使用 v-once,這樣哪怕這些數(shù)據(jù)變化,vue 也會(huì)跳過更新,是一種代碼優(yōu)化手段。

  • 我們只需要作用的組件或元素上加上 v-once 即可。

補(bǔ)充:

  • vue3.2 之后,又增加了 v-memo,這個(gè)指令可以有條件的緩存模板并控制他們的更新。

  • v-once 的原理:編譯器發(fā)現(xiàn)有 v-once 時(shí),會(huì)將首次計(jì)算結(jié)果存入緩存對(duì)象,組件再次渲染時(shí)就會(huì)從緩存獲取,從而避免再次計(jì)算。

34. 什么場景使用嵌套路由

  • 在平時(shí)開發(fā)中,應(yīng)用的有些界面是由多層嵌套的組件組合而來的,這種情況下,url 各部分通常對(duì)應(yīng)某個(gè)嵌套的組件,vue-router 中可以使用嵌套路由表示這種關(guān)系。

  • 表現(xiàn)形式是在兩個(gè)路由間切換時(shí),他們有公用的視圖內(nèi)容。此時(shí)通常提取一個(gè)父組件,內(nèi)部放上 view-router,從而形成物理上的嵌套,和邏輯上的嵌套對(duì)應(yīng)起來。定義嵌套路由時(shí)使用 children 屬性組織嵌套關(guān)系

  • 原理上是在 router-view 組件內(nèi)部判斷其所處嵌套的深度,將這個(gè)深度作為匹配組件數(shù)組 matched 的索引,獲取對(duì)應(yīng)渲染組件并渲染之。

如果你說不出來,可以直接舉例子。當(dāng)我開發(fā)一個(gè)頁面時(shí),如果需要顯示一個(gè)頂部導(dǎo)航欄,通過導(dǎo)航欄跳轉(zhuǎn)到不同的頁面,而頂部的導(dǎo)航欄又必須要在每個(gè)頁面顯示時(shí),就可以使用嵌套路由;還可以舉例,當(dāng)我需要查看某個(gè)列表的詳情頁面時(shí),往往需要嵌套路由 (detail/:id

35. 如何監(jiān)聽 Vuex 狀態(tài)變化?

  • watch

  • store.subscribe()

watch 方式,可以以字符串形式監(jiān)聽 $store.state.xx; subscribe 方法參數(shù)是一個(gè)回調(diào)函數(shù),回調(diào)函數(shù)接受mutation 對(duì)象和 state 對(duì)象,可以通過 mutation.type 判斷監(jiān)聽的目標(biāo)。 wtach 方法更簡單好用, subscribe 會(huì)略繁瑣,一般

36. Vue 實(shí)例掛載過程發(fā)生了什么?

  • 掛載實(shí)例的過程就是 app.mount()的過程,整體上就做了兩件事:初始化建立更新機(jī)制

  • 初始化會(huì)創(chuàng)建組件實(shí)例、初始化組件狀態(tài)創(chuàng)建各種響應(yīng)式數(shù)據(jù)

  • 簡歷更新機(jī)制這一步會(huì)立即執(zhí)行一次組件更新函數(shù),這會(huì)首次執(zhí)行渲染函數(shù)并執(zhí)行 patch 將前面獲得vnode 轉(zhuǎn)換為 dom;同時(shí)會(huì)創(chuàng)建它內(nèi)部響應(yīng)式數(shù)據(jù)和組件更新函數(shù)之間的依賴關(guān)系,這使得以后數(shù)據(jù)變化時(shí)會(huì)執(zhí)行對(duì)應(yīng)的更新函數(shù)。

37. key 的作用

  • key 的作用主要是為了更高效的更新虛擬 DOM 。

  • keyvuepatch 過程中判斷兩個(gè)節(jié)點(diǎn)是否是相同節(jié)點(diǎn)的關(guān)鍵條件(另一個(gè)是元素類型),如果不設(shè)置 key,它的值就是 undefined,vue 則可能永遠(yuǎn)認(rèn)為這是兩個(gè)相同節(jié)點(diǎn),只能去做更新操作,這造成了大量的 dom 更新操作,明顯是不可取的。

  • 實(shí)際使用的過程中必須設(shè)置 key,而且應(yīng)該盡量避免使用數(shù)組索引,這可能導(dǎo)致一些隱藏 bug

38. watch 和 watchEffect

  • watchEffect立即運(yùn)行函數(shù),被動(dòng)地追蹤它的依賴,傳入的函數(shù)即是依賴收集的數(shù)據(jù)源,也是回調(diào)函數(shù);watch 偵測一個(gè)或多個(gè)響應(yīng)式數(shù)據(jù)源,在數(shù)據(jù)源變化時(shí)調(diào)用一個(gè)回調(diào)函數(shù),通過 immediate 選項(xiàng)也可以設(shè)置立即執(zhí)行一次。

  • watchEffect是一種特殊的 watch。如果不關(guān)心響應(yīng)式數(shù)據(jù)前后的值,可以使用 watchEffect。其他情況都可以用 watch。

39. 父子組件創(chuàng)建、掛載順序

parent created  -> child created -> child mounted -> parent mounted

原因:Vue 創(chuàng)建是一個(gè)遞歸的過程,先創(chuàng)建父組件,有子組件就會(huì)創(chuàng)建子組件,因此創(chuàng)建時(shí)先有父組件再有子組件;子組件首次創(chuàng)建時(shí)會(huì)添加 Mounted 鉤子到隊(duì)列,等到 patch 結(jié)束再執(zhí)行它們,可見子組件的 mounted 鉤子是選進(jìn)入到隊(duì)列中的,因此等到 patch 結(jié)束執(zhí)行這些鉤子時(shí)也先執(zhí)行。

40. 說說你對(duì) Vuex 的理解

  • vuex是一個(gè)專門為vue應(yīng)用開發(fā)的狀態(tài)管理模式庫,

  • 當(dāng)你遇到多個(gè)組件共享狀態(tài)時(shí)或者項(xiàng)目中的組件難以管理的時(shí)候就可以使用vuex,它以一個(gè)全局單例模式管理全局的狀態(tài)。

  • 基本核心概念有 state、mutation、action、getters、module等

  • 說些使用過程的感受 ts不友好 模塊使用繁瑣 頁面刷新數(shù)據(jù)也會(huì)消失

41. 什么是遞歸組件?使用場景有哪些?

  • 如果某個(gè)組件通過組件名稱引用它自己,這種情況就是遞歸組件。

  • 類似 Tree、Menu 這類組件,它們的節(jié)點(diǎn)往往包含子節(jié)點(diǎn),子節(jié)點(diǎn)結(jié)構(gòu)和父節(jié)點(diǎn)往往是相同的。這類組件的數(shù)據(jù)往往也是樹形結(jié)構(gòu),這種都是使用遞歸組件的典型場景。

42. 你寫過自定義指令嗎?

使用自定義指令分為定義、注冊(cè)、和使用

  • 定義有兩種方式,對(duì)象和函數(shù)形式,前者類似組件定義,有各種生命周期;后者只會(huì)在 mountedupdated 時(shí)執(zhí)行

  • 注冊(cè):可以使用 app.directive 全局注冊(cè) 也可以通過選項(xiàng)局部注冊(cè)

  • 使用時(shí)在注冊(cè)名稱前加上 v-即可。

  • v-copy 復(fù)制粘貼

  • v-lazy 圖片懶加載

  • v-debounce 防抖

  • v-permission 按鈕權(quán)限

  • v-longpress 長按

43. Vue3新特性

API 層面

  • Composition API

  • setup 語法糖

  • Teleport 傳送門

  • Fragments 可以多個(gè)根節(jié)點(diǎn)

  • Emits

  • createRenderer 自定義渲染器

  • SFC 狀態(tài)驅(qū)動(dòng) css 變量 (v-bind in <style>)

此外,Vue3在框架層面也有很多兩點(diǎn)和改進(jìn)

  • 更快

    • 虛擬 DOM 重寫

    • 編譯器優(yōu)化:靜態(tài)提升、patchFlagsblock

    • 基于 Proxy 的響應(yīng)式系統(tǒng)

  • 更?。焊玫膿u樹優(yōu)化

  • 更容易維護(hù):TS + 模塊化

  • 更容易擴(kuò)展

    • 獨(dú)立的響應(yīng)化模塊

    • 自定義渲染器

44. Vue3設(shè)計(jì)目標(biāo)和優(yōu)化點(diǎn)

最大設(shè)計(jì)目標(biāo)就是替代 Vue2,為了實(shí)現(xiàn)這一點(diǎn),Vue3 在以下幾個(gè)方面做了很大改進(jìn),如:易用性,框架性能、擴(kuò)展性、可維護(hù)性、開發(fā)體驗(yàn)等

  • 易用性方面:主要有 API 簡化 v-model 變成了 v-modelsync 修飾符的結(jié)合體。類似的還有 h(type,props,children) 函數(shù)中的 props 不用考慮區(qū)分屬性、特性、事件等,框架替我們判斷,易用性增。

  • 開發(fā)體驗(yàn)方面:新組建 Teleport Fragment Suspense 等都會(huì)簡化特定場景的代碼編寫。 setup 語法糖更是極大提升了我們的開發(fā)體驗(yàn)。

  • 擴(kuò)展性方面提升: 如獨(dú)獨(dú)立的 reactivity 模塊,custom render API

  • 可維護(hù)性方面主要是 Composition API,更容易編寫高復(fù)用性的業(yè)務(wù)邏輯。還有對(duì)TS支持的提升。

  • 性能方面:編譯器優(yōu)化、基于 Proxy 的響應(yīng)式系統(tǒng)。

  • 。。。

45. Vue3性能提升體現(xiàn)在哪些方面?

  • 代碼方面:全新的響應(yīng)式API,基于 Proxy 實(shí)現(xiàn),初始化事件和內(nèi)存占用均大幅改進(jìn);

  • 編譯方面:做了更多編譯優(yōu)化處理,比如靜態(tài)提升、動(dòng)態(tài)內(nèi)容標(biāo)記、事件緩存、區(qū)塊等,可以有效跳過大量diff過程

  • 打包方面:更好的支持 tree-shaking ,因此體積更小,加載更快.(因?yàn)関ue3 所有的API都通過ES6模塊化的方式引入,這樣就能讓webpack或rollup等打包工具在打包時(shí)對(duì)沒有用到API進(jìn)行剔除,最小化bundle體積

46. $attrs$listeners 是做什么的?

$attrs 獲取沒有在 props 中定義的屬性,v-bind="$attrs" 可以用于屬性透傳$listeners 用于獲取事件,vue3 中已經(jīng)移除合并到 attrs 中,使用起來更方便

47. Composition API 和 Option API 有何不同?

Composition API 是一組API,包括 Reactivity API、生命鉤子、依賴注入,使用戶可以通過導(dǎo)入函數(shù)方式編寫組件,而 Options API 則通過聲明組件選項(xiàng)的對(duì)象形式編寫組件。

Composition API 更簡潔、邏輯復(fù)用更高效。解決的過去 Options APImixins 的各種缺點(diǎn)(會(huì)沖突很混亂);另外 Composition API 更自由,沒有 Options API 那樣固定的寫法,并且可以更有效的將邏輯代碼組織在一起,而不用東一塊西一塊搞得很混亂,最后 Composition API 擁有更好的類型推斷,對(duì) ts 支持友好。

48. 你知道哪些 Vue 最佳實(shí)踐

編碼風(fēng)格方面:

  • 組件命名時(shí)使用 多詞風(fēng)格避免和html元素沖突

  • 屬性名峰命名,模板或jsx中使用 肉串命名

  • v-for 務(wù)必加上key 且不要和v-if寫在一起‘’

性能方面:

  • 路由懶加載減少應(yīng)用尺寸

  • SSR 減少首屏加載事件

  • v-once v-memo

  • 長列表 虛擬滾動(dòng)技術(shù)

  • 對(duì)于深層嵌套對(duì)象的大數(shù)據(jù)可以使用 shallowRefshallowReactive 降低開銷

  • 避免不必要的組件抽象

49. mutation 和 action 的區(qū)別?

mutation 用于修改 stateaction 用于提交一個(gè) mutation,而且 action 可以包含異步操作

50. 如何從0實(shí)現(xiàn)vuex

  • 要實(shí)現(xiàn)一個(gè) Store 存儲(chǔ)全局狀態(tài)

  • 要提供修改狀態(tài)所需的API:commit({type, payload}), dispatch(type,payload)

實(shí)現(xiàn) Store,可以定義 Store 類,構(gòu)造函數(shù)接受選項(xiàng) options,設(shè)置屬性 state 對(duì)外暴露狀態(tài),提供 commitdispatch 修改屬性。這里需要設(shè)置 state 為響應(yīng)式對(duì)象,同時(shí)將 Store 定義為一個(gè) Vue 插件(install方法)。

commit 可以獲取用戶傳入 mutations  并執(zhí)行它,這樣可以按用戶提供的方法修改狀態(tài),dispatch 類似,但是 dispatch 需要返回一個(gè) Promise 給用戶用于處理異步結(jié)果。

關(guān)于“Vue面試題及答案有哪些”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Vue面試題及答案有哪些”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI