亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue面試題及答案有哪些

發布時間:2023-01-04 09:06:08 來源:億速云 閱讀:152 作者:iii 欄目:編程語言

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

1. 簡述 Vue 生命周期

答題思路:

  • Vue 生命周期是什么?

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

  • Vue 生命周期的流程?

  • 結合實踐

  • 擴展:在 Vue3 變化 Vue 生命周期的變化 

回答范例:

  • 生命周期這個詞應該是很好理解的,在我們生活中就會常常碰到,比如談到一個人的生命周期,我們會說人這一生會經歷嬰兒、兒童、少年、青年、中年、老年這幾個階段。 而 Vue 的生命周期也是如此,在 Vue 中的每個組件都會經歷從創建掛載更新再到銷毀這幾個階段,而在這些階段中,Vue 會運行一種叫做生命周期鉤子的函數,方便我們在特定的階段有機會添加上我們自己的代碼。

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

  • 這幾個階段對應的鉤子函數 API依次為:beforeCreate create beforeMount mounted beforeUpdate updated activated(keep-alive 激活時調用) deactivated(keep-alive 停用時調用) beforeDestory destoryed errorCaptured(捕獲子孫組件錯誤時調用)

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

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

  • 在 Vue3 中: setup 是比 created 先執行的而且沒有 beforeCreate 和  created

2. Vue 中如何做權限管理

  • 權限管理一般需求就是對頁面權限和按鈕權限的管理

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

    后端方案會把所有頁面路由信息存在數據庫中,用戶登錄的時候根據其角色查詢得到其能訪問的所有路由信息返回給前端,前端再通過 addRoute 動態添加路由信息。

    按鈕權限的控制通常會實現一個指令,例如 v-permission,將按鈕要求角色通過值傳給 v-permission 指令,在指令的 mounted 鉤子中可以判斷當前用戶角色和按鈕是否存在交集,有就保留按鈕,沒有就移除按鈕。

  • 純前端方案的優點是實現簡單,不需要額外權限管理頁面,但是維護起來問題比較大,有新的頁面和角色需求就要修改前端代碼和重新打包部署服務端方案就不存在這個問題,通過專門的角色和權限管理頁面,配置頁面和按鈕權限信息到數據庫,應用每次登陸時獲取的都是最新的路由信息。

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

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

回答思路:

  • 什么是雙向綁定?

  • 雙向綁定的好處?

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

  • 雙向綁定的使用方式、使用細節、Vue3中的變化

  • 原理實現描述

回答:

  • Vue中的雙向綁定是一個指令 v-model ,它可以綁定一個響應式數據到視圖,同時視圖中變化也能改變該值。

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

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

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

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

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

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

  • props

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

  • $children(Vue3中廢除)$parent

  • $attrs$listeners(Vue3中廢除)

  • ref

  • $root

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

  • vuexpinia

  • provide + inject

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

  • 父子組件之間可以使用

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

  • 兄弟組件之間可以使用

    $parent / $root/ eventbus / vuex

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

    eventbus / vuex pinia / provide + inject

5.你了解哪些 Vue 性能優化方法?

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

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

  • keep-alive 緩存頁面:避免重復創建組件實例,且能保存緩存組件狀態

<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 復用 DOM:避免重復創建組件

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

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

  • 長列表性能優化:如果是大數據長列表,可采用虛擬滾動,只渲染少部分區域的內容。一些開源庫(vue-virtual-scroller / vue-virtual-scroll-grid

  • 事件的銷毀:Vue組件銷毀時,會自動解綁它的全部指令以及事件監聽器,但是僅限于組件本身的事件。

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

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

  • 子組件分割策略:較重的狀態組件適合拆分

  • SSR 服務端渲染 解決首屏渲染慢的問題

6. 刷新后 Vuex 狀態丟失怎么解決?

思路:

  • 刷新后 Vuex 狀態為什么會丟失?

  • 解決方法

  • 第三方庫以及原理探討

  • 個人理解

回答:

  • 因為 Vuex 只是在內存中保存狀態,刷新后就會丟失,如果要持久化就要存起來。

  • 可以是用 localStorage 存儲 Vuex 的狀態,store 中把值取出來作為 state 的初始值,提交 mutation 的時候就存入 localStorage

  • 可以用 vuex-persistvuex-persistedstate 這種插件,可以通過插件選項控制哪些需要持久化。內部的原理就是通過訂閱 mutation 變化做統一處理。

  • 這里有兩個問題,一是如果用戶手動改了 localStorage怎么辦?那我 Vuex 里的狀態不是也改變了?二是由于 localStorage API 的原因只能存儲字符串,所以我們只能將數據通過 JSON.stringify 轉換為字符串,而當我們存儲的數據為 MapSetFunction 這種引用類型的數據時,JSON.stringify 轉換后會變味 {} 而丟失。

對應第一個問題我的解決方法是可以通過 監聽 storage 事件來清除數據

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

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

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

思路:

  • 屬性攔截的幾種方式

  • defineProperty的問題

  • Proxy的優點

  • 其他考量

回答:

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

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

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

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

8. 怎么實現路由懶加載?

思路:

  • 必要性

  • 何時用

  • 怎么用

  • 使用細節

回答:

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

  • 一般來說,對于所有的路由都使用動態導入是個好主意

  • component 選項配置一個返回 Promise組件的函數就可以定義懶加載路由.例如:

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

  • 結合注釋

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

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

9. history模式 和 hash 模式有何區別?

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

  • hash模式在地址欄現實的時候有一個 #,這種方式使用和部署都較簡單;history模式url看起來更優雅沒關,但是應用在部署時需要做特殊配置,web服務器需要做回退處理,否則會出現刷新頁面404的問題。

  • 在實現上 hash模式是監聽hashchange事件觸發路由跳轉,history模式是監聽popstate 事件觸發路由跳轉。

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

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

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

    • created 中想要獲取 DOM;

    • 響應式數據變化后獲取 DOM 更新后的狀態;

  • nextTick 的原理:在 Vue 內部,nextTick 之所以能夠讓我們看到 DOM 更新后的結果,是因為我們傳入的 callback 會被添加到隊列刷新函數的后面,這樣等隊列內部的更新函數都執行完畢,所有 DOM 操作也就結束了,callback 自然能夠獲取最新的 DOM 值。

11. v-for 和 v-if 優先級

先回答答案:vue2 中, v-for 的優先級更高 但是在 vue3 中, v-if 的優先級更高

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

vue2文檔vue3文檔

12. 如何監聽 Vuex 狀態變化?

  • watch

  • store.subscribe()

watch 方式,可以以字符串形式監聽 $store.state.xx; subscribe 方法參數是一個回調函數,回調函數接受mutation 對象和 state 對象,可以通過 mutation.type 判斷監聽的目標。 wtach 方法更簡單好用, subscribe 會略繁瑣,一般用 vuex 插件中(可以提一下vuex的持久化插件vuex-persistvuex-persistedstate

13. 你覺得 Vuex 有什么缺點?

  • 不支持持久化,頁面刷新狀態就會丟失

  • 使用模塊比較繁瑣

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

vue3 + pinia 會是更好的組合。

14. ref 和 reactive 異同點?

  • 兩者都能返回響應式對象,ref 返回的是一個響應式Ref 對象, reactive 返回的是響應式代理對象。

  • ref 通常是處理單值得響應式,reactive 用于處理對象類型的數據響應式

  • ref 需要通過 .value 訪問, 在視圖中會自動脫 ref,不需要 .valueref 可以接收對象或數組但內部依然是 reactive 實現的;reactive 如果接收 Ref 對象會自動脫 ref ;使用展開運算符展開 reactive 返回的響應式對象會使其失去響應性,可以結合 toRefs()將值轉換為 Ref 對象后再展開。

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

16. Vue 中如何擴展一個組件?

  • 邏輯擴展:mixinsextendscomposition api:

  • 內容擴展:slots

mixins 很靈活,但是會沖突很混亂。extends 是一個不太常用的選項,更 mixins 的不同是它只能擴展單個對象,優先級比 mixins 高。

混入的數據和方法 不能明確判斷來源 而且可能和當前組件內變量 產生命名沖突,composition api 可以很好解決這些問題,利用獨立出來的響應式模塊可以很方便的編寫獨立邏輯并提供響應式數據局,增強代碼的可讀性和維護性。

擴展:Vue.mixin(全局混入)  Vue.extend(有點像是 類/組件的繼承 創建一個子類)

17. vue-loader 是什么?

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

  • 因為有了 vue-loader,我們才能用 .vue 文件形式編寫代碼,將代碼分割為 template script style

  • webpack 在打包的時候,會以 loader 的方式調用 vue-loader

  • vue-loader 被執行時,它會對 SFC 中的每個語言塊用單獨的 loader 鏈處理,最后將這些單獨的塊裝配成最終的組件模塊

18. 子組件能否修改父組件數據

不能直接改。

組件化開發中有一個單向數據流原則,不在子組件修改父組件數據是個常識

如果你確實需要改,請通過emit向父組件發送一個事件,在父組件中修改

19. 怎么定義動態路由,怎么獲取傳過來的動態參數?

我么可以在路徑中使用一個動態字段來實現,例如/users/:id 其中 :id 就是路徑參數。 可以通過 this.$route.parmas獲取,參數還可以有多個, $route 對象還公開了其他有用的信息如 query hash等。

20. 說說對 Vue 數據響應式的理解

思路:

  • 什么是響應式?

  • 為什么vue需要響應式?

  • 有什么好處?

  • vue的響應式怎么實現的,有哪些優缺點?

  • vue3中的響應式的新變化

回答:

  • 數據響應式就是 能夠監測到數據變化并且做出響應的一種機制

  • vue 中要解決的一個核心問題就是連接數據層和視圖層,通過數據變化驅動視圖更新,要做到這點就需要對數據做響應式處理。

  • 通過數據響應式加上虛擬 DOMpatch 算法,我們只需要操作數據,關心業務,完全不需要接觸繁瑣的 DOM 操作,打打提升了開發效率,降低開發難度。

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

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

21. 從 template 到 render 做了什么

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

思路:

  • 引入編譯器概念

  • 說明編譯器的必要性

  • 闡述編譯器工作流程

回答:

  • Vue 中有個獨特的編譯模塊,稱為 compiler,它的主要作用是將 template 編譯為 js 可執行的 render 函數

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

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

22. 如何緩存和更新組件

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

  • Vue3 結合 vue-router 使用變化非常大,之前是 keep-alive 包含 router-view,現在是 router-view 包含 keep-alive

  • 緩存后如果想要獲取數據可以使用 actived 鉤子 或者 beforeRouteEntervue-router 的一個守衛)

  • keep-alive 是一個通用組件,它內部定義了一個 map,緩存創建過的組件實例,它返回的渲染函數內部會查找內嵌的 component 組件對應組件的 vnode,如果改組件在map中存在就直接返回它。由于 componentis 屬性是一個響應式數據,因此只要它變化,keep-aliverender 函數就會重新執行。

23. 虛擬DOM

  • 虛擬 DOM 是什么? 虛擬 DOM 的本質就是一個 Javascript 對象。

  • 為什么要引入虛擬 DOM?(好處) 它能有效減少操作 DOM 的次數,方便實現跨平臺

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

24. 什么是異步組件

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

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

  • 使用異步組件最簡單的方式是直接給 defineAsyncComponet 指定一個 loader 函數,結合 ES 模塊 動態導入函數 import 可以快速實現。Vue3 還可以結合 Suspense 組件使用異步組件。

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

25. 說說Vue長列表優化思路

  • 避免大數據量:可以采用分頁的方式獲取

  • 避免渲染大量數據:vue-virtual-scroller等虛擬滾動方案,只渲染視口范圍內的數據

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

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

  • 按需加載數據:可以采用 懶加載 方式,在用戶需要的時候在加載數據。

26. computed & watch

  • computed 是計算屬性,watch 是偵聽器。

  • computed 通常用于處理模版中復雜的邏輯,而 watch 通常用于需要監聽一個響應式對象的變化而做一些操作的時候

  • watch 可以進行異步操作,computed 不行。

  • 計算屬性傳遞一個對象 有 setget 兩個選項,是它稱為即可讀又可寫的計算屬性,如果傳遞的是函數的話默認就是 get 選項,watch 可以傳遞一個對象,設置deep、immediate等選項

  • vue3watch 發生了一些變化,例如不能再偵測一個點操符之外的字符串表達式,reactivity API 中新出的 watchwatchEffect 可以完全替代 watch 選項,而且功能更加強大

27. SPA 和 SSR的區別是什么?

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

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

  • 選擇上,如果有首屏加載優化需求,SEO需求時,就可以考慮SSR。

  • 但并不是只有這一種替代方案,比如對一些不常變化的靜態網站,SSR反而浪費資源,我們可以考慮預渲染的方案。另外 nuxt.js/next.js 中給我們提供了SSG靜態網站生成方案也是很好的靜態站點解決方案,結合一些CI手段,可以起到很好的優化效果。

28. diff 算法

回答思路:

  • diff算法是干什么的?

  • 必要性

  • 何時執行

  • 具體執行方式

  • 拔高:說一下vue3中的優化

回答:

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

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

  • vuediff 執行的時刻是組件內響應式數據變更觸發實例執行其更新函數時,更新函數會再次執行 render函數 獲得最新的 虛擬DOM ,然后執行 patch函數對比新舊虛擬DOM,將其轉化為對應的 DOM 操作。

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

    • 新的子節點是文本,老的子節點是數組則清空,并設置文本;

    • 新的子節點是文本,老的子節點是文本則直接更新文本;

    • 新的子節點是數組,老的子節點是文本則清空文本,并創建新子節點數組中的子元素;

    • 新的子節點是數組,老的子節點也是數組,那么比較兩組子節點,更新細節blabla

    • 首先判斷兩個節點是否為相同同類節點,不同則刪除重新創建

    • 如果雙方都是文本則更新文本內容

    • 如果雙方都是元素節點則遞歸更新子元素,同時更新元素屬性

    • 更新子節點時又分了幾種情況:

  • vue3 中引入的更新策略:編譯期優化 patchFlagsblock

29. 如何從0到1架構一個Vue項目,說說有哪些步驟,插件,目錄結構怎么組織

  • 從 0 創建項目我大致會做以下事情:項目構建、引入必要插件、代碼規范、提交規范、常用庫和組件

  • 目前vue3項目我會用vite或者create-vue創建項目

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

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

  • 下面是代碼規范: editorconfig、prettier、eslint

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

  • 目錄結構我喜歡按照下面的結構來

+ |- /src
+   |- /assets 存放資源
+     |- /img   
+     |- /css   
+     |- /font   
+     |- /data   
+   |- base-ui  存放多個項目中都會用到的公共組件
+   |- components 存放這個項目用到的公共組件
+   |- hooks 存放自定義hook
+   |- views 視圖
+   |- store 狀態管理
+   |- router 路由
+   |- service 網絡請求
+   |- utils 工具
+   |- global 全局注冊、全局常量..

30. 你如何實現一個Vue-Router

一個 SPA 應用的路由需要解決的問題時頁面跳轉內容改變同時不刷新,同時路由還需要已插件形式存在,所以:

  • 首先我會定義一個 createRouter 函數,返回路由器實例,實例內部做幾件事;


    • 保存用戶傳入的配置項

    • 監聽 hash 或者 popstate 事件

    • 回調里根據 path 匹配對應路由

  • router 定義成一個 Vue 插件,即實現 install 方法,內部做兩件事:


    • 實現兩個全局組件:router-linkrouter-view,分別實現頁面跳轉和內容顯示

    • 定義兩個全局變量:$router$route,組件內可以訪問當前路由和路由器實例

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

  • 在項目規模變大的之后,單獨一個store對象會過于龐大臃腫,此時通過模塊方式可以拆分來便于維護

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

  • 使用時需要注意訪問子模塊狀態時需要加上注冊模塊名。但同時gettersmutationsactions又在全局空間中,使用方式和之前一樣。如果要做到完全拆分,需要在子模塊加上 namespace選項,此時再訪問它們就要加上命名空間前綴。

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

32. vue 組件為什么只能有1個根節點

  • vue2 中組件確實只能有一個跟,但 vue3 中組件已經可以多根組件了。

  • 之所以需要這樣是因為 vdom 是一顆單根樹形結構,patch 方法在遍歷的時候從根節點開始遍歷,它要求只有一個根節點。組件也會轉換為一個 vdom,自然應該滿足這個要求。

  • vue3 中之所以可以寫多個根節點,是因為引入了 Fragment 的概念,這是一個抽象的節點,如果發現組件時多根的,就創建一個 Fragment 節點,把多個根節點作為它的 children。將來 pathch 的時候,如果發現是一個 Fragment 節點,則直接遍歷 children 創建或更新。

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

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

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

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

補充:

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

  • v-once 的原理:編譯器發現有 v-once 時,會將首次計算結果存入緩存對象,組件再次渲染時就會從緩存獲取,從而避免再次計算。

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

  • 在平時開發中,應用的有些界面是由多層嵌套的組件組合而來的,這種情況下,url 各部分通常對應某個嵌套的組件,vue-router 中可以使用嵌套路由表示這種關系。

  • 表現形式是在兩個路由間切換時,他們有公用的視圖內容。此時通常提取一個父組件,內部放上 view-router,從而形成物理上的嵌套,和邏輯上的嵌套對應起來。定義嵌套路由時使用 children 屬性組織嵌套關系

  • 原理上是在 router-view 組件內部判斷其所處嵌套的深度,將這個深度作為匹配組件數組 matched 的索引,獲取對應渲染組件并渲染之。

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

35. 如何監聽 Vuex 狀態變化?

  • watch

  • store.subscribe()

watch 方式,可以以字符串形式監聽 $store.state.xx; subscribe 方法參數是一個回調函數,回調函數接受mutation 對象和 state 對象,可以通過 mutation.type 判斷監聽的目標。 wtach 方法更簡單好用, subscribe 會略繁瑣,一般

36. Vue 實例掛載過程發生了什么?

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

  • 初始化會創建組件實例初始化組件狀態創建各種響應式數據

  • 簡歷更新機制這一步會立即執行一次組件更新函數,這會首次執行渲染函數并執行 patch 將前面獲得vnode 轉換為 dom;同時會創建它內部響應式數據和組件更新函數之間的依賴關系,這使得以后數據變化時會執行對應的更新函數。

37. key 的作用

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

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

  • 實際使用的過程中必須設置 key,而且應該盡量避免使用數組索引,這可能導致一些隱藏 bug

38. watch 和 watchEffect

  • watchEffect立即運行函數,被動地追蹤它的依賴,傳入的函數即是依賴收集的數據源,也是回調函數;watch 偵測一個或多個響應式數據源,在數據源變化時調用一個回調函數,通過 immediate 選項也可以設置立即執行一次。

  • watchEffect是一種特殊的 watch。如果不關心響應式數據前后的值,可以使用 watchEffect。其他情況都可以用 watch

39. 父子組件創建、掛載順序

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

原因:Vue 創建是一個遞歸的過程,先創建父組件有子組件就會創建子組件,因此創建時先有父組件再有子組件;子組件首次創建時會添加 Mounted 鉤子到隊列,等到 patch 結束再執行它們,可見子組件的 mounted 鉤子是選進入到隊列中的,因此等到 patch 結束執行這些鉤子時也先執行。

40. 說說你對 Vuex 的理解

  • vuex是一個專門為vue應用開發的狀態管理模式庫,

  • 當你遇到多個組件共享狀態時或者項目中的組件難以管理的時候就可以使用vuex,它以一個全局單例模式管理全局的狀態。

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

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

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

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

  • 類似 TreeMenu 這類組件,它們的節點往往包含子節點,子節點結構和父節點往往是相同的。這類組件的數據往往也是樹形結構,這種都是使用遞歸組件的典型場景。

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

使用自定義指令分為定義、注冊、和使用

  • 定義有兩種方式,對象和函數形式,前者類似組件定義,有各種生命周期;后者只會在 mountedupdated 時執行

  • 注冊:可以使用 app.directive 全局注冊 也可以通過選項局部注冊

  • 使用時在注冊名稱前加上 v-即可。

  • v-copy 復制粘貼

  • v-lazy 圖片懶加載

  • v-debounce 防抖

  • v-permission 按鈕權限

  • v-longpress 長按

43. Vue3新特性

API 層面

  • Composition API

  • setup 語法糖

  • Teleport 傳送門

  • Fragments 可以多個根節點

  • Emits

  • createRenderer 自定義渲染器

  • SFC 狀態驅動 css 變量 (v-bind in <style>)

此外,Vue3在框架層面也有很多兩點和改進

  • 更快

    • 虛擬 DOM 重寫

    • 編譯器優化:靜態提升、patchFlagsblock

    • 基于 Proxy 的響應式系統

  • 更小:更好的搖樹優化

  • 更容易維護:TS + 模塊化

  • 更容易擴展

    • 獨立的響應化模塊

    • 自定義渲染器

44. Vue3設計目標和優化點

最大設計目標就是替代 Vue2,為了實現這一點,Vue3 在以下幾個方面做了很大改進,如:易用性,框架性能、擴展性、可維護性、開發體驗等

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

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

  • 擴展性方面提升: 如獨獨立的 reactivity 模塊,custom render API

  • 可維護性方面主要是 Composition API,更容易編寫高復用性的業務邏輯。還有對TS支持的提升。

  • 性能方面:編譯器優化、基于 Proxy 的響應式系統。

  • 。。。

45. Vue3性能提升體現在哪些方面?

  • 代碼方面:全新的響應式API,基于 Proxy 實現,初始化事件和內存占用均大幅改進;

  • 編譯方面:做了更多編譯優化處理,比如靜態提升、動態內容標記、事件緩存、區塊等,可以有效跳過大量diff過程

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

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

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

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

Composition API 是一組API,包括 Reactivity API、生命鉤子、依賴注入,使用戶可以通過導入函數方式編寫組件,而 Options API 則通過聲明組件選項的對象形式編寫組件。

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

48. 你知道哪些 Vue 最佳實踐

編碼風格方面:

  • 組件命名時使用 多詞風格避免和html元素沖突

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

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

性能方面:

  • 路由懶加載減少應用尺寸

  • SSR 減少首屏加載事件

  • v-once v-memo

  • 長列表 虛擬滾動技術

  • 對于深層嵌套對象的大數據可以使用 shallowRefshallowReactive 降低開銷

  • 避免不必要的組件抽象

49. mutation 和 action 的區別?

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

50. 如何從0實現vuex

  • 要實現一個 Store 存儲全局狀態

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

實現 Store,可以定義 Store 類,構造函數接受選項 options,設置屬性 state 對外暴露狀態,提供 commitdispatch 修改屬性。這里需要設置 state 為響應式對象,同時將 Store 定義為一個 Vue 插件(install方法)。

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

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vue
AI

孝义市| 永嘉县| 兴化市| 越西县| 阳曲县| 龙江县| 怀安县| 长白| 福贡县| 西宁市| 资兴市| 阳西县| 江陵县| 正镶白旗| 多伦县| 新民市| 来凤县| 太湖县| 兴海县| 柳河县| 边坝县| 法库县| 汕头市| 朝阳县| 周口市| 九龙坡区| 黄浦区| 平南县| 中山市| 蒲江县| 越西县| 鹤庆县| 乃东县| 江达县| 日喀则市| 昌吉市| 清新县| 英德市| 如东县| 徐汇区| 浪卡子县|