日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系

發(fā)布時間:2023/12/4 vue 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

「面試專欄」前端面試之vuejs篇

  • 🖼?序言
  • 🎙?一、vue2.x基礎(chǔ)知識預(yù)備
  • 📻二、vue2.x基礎(chǔ)知識常見面試題
    • 1、請說出vue.cli項目中src目錄每個文件夾和文件的用法?
    • 2、vue.cli中怎樣使用自定義的組件?有遇到過哪些問題?
    • 3、v-show和v-if的區(qū)別
    • 4、為何v-for中要用key
    • 5、描述Vue組件生命周期
      • (1)單組件生命周期
      • (2)父子組件生命周期關(guān)系
    • 6、Vue組件如何通訊(常見)
    • 7、描述組件渲染和更新的過程
    • 8、vue如何處理刷新數(shù)據(jù)不丟失
    • 9、雙向數(shù)據(jù)綁定 v-model 的實現(xiàn)原理
    • 10、computed 有何特點(diǎn)
    • 11、為何組件data必須是一個函數(shù)
    • 12、ajax請求應(yīng)該放在哪個生命周期
    • 13、如何將組件所有props傳遞給子組件?
    • 14、如何自己實現(xiàn)v-model
    • 15、多個組件有相同的邏輯,如何抽離?
    • 16、何時要使用異步組件
    • 17、何時使用keep-alive
    • 18、何時需要使用beforeDestory
    • 19、什么是作用域插槽
    • 20、vuex中action和mutation有何區(qū)別
    • 21、vue-router常用的路由模式
    • 22、如何配置vue-router異步加載
    • 23、scope是怎么實現(xiàn)的
    • 24、vue常用性能優(yōu)化方式
  • 📟三、vue2.x原理知識預(yù)備
  • 📠四、vue原理知識常見面試題
    • 1、對MVVM的理解
    • 2、監(jiān)聽data變化的核心 API 是什么
    • 3、vue如何監(jiān)聽數(shù)組變化
    • 4、請描述響應(yīng)式原理
    • 5、請用vnode描述一個DOM結(jié)構(gòu)
    • 6、diff算法的時間復(fù)雜度
    • 7、簡述diff算法過程
    • 8、vue模板編譯的原理是什么
    • 9、vue為何是異步渲染,$nextTick有何用?
    • 10、SPA單頁面應(yīng)用是什么?
    • 11、hash和history的區(qū)別是什么?
      • (1)hash
      • (2)history
    • 12、hash和history兩者的選擇
  • 🖨?五、vue3.x知識預(yù)備
  • ??六、vue3.x常見面試題
    • 1、vue3和vue2有什么優(yōu)勢?
    • 2、描述vue3生命周期
    • 3、如何看待Composition API和Options API
    • 4、如何理解ref、toRef和toRefs
      • (1)ref是什么
      • (2)toRef是什么
      • (3)toRefs是什么
    • 5、vue3升級了哪些重要的功能?
    • 6、Composition API如何實現(xiàn)代碼的邏輯復(fù)用?
    • 7、Vue3如何實現(xiàn)響應(yīng)式?
    • 8、Watch和watchEffect的區(qū)別是什么?
    • 9、setup中如何獲取組件實例?
    • 10、vue3為何比vue2快?
    • 11、vite是什么?
    • 12、Composition API和React hooks的對比
  • 📸七、結(jié)束語
  • 🐣彩蛋 One More Thing
    • 🏷?往期推薦
    • 🏷?番外篇

🖼?序言

對于前端來說, vuejs 是一大常考點(diǎn)。基本上只要候選人的簡歷上有涉及到 vue 的內(nèi)容,那么面試官一般都會考察。那么,對于 vue 來說,我們需要從 vue2 到 vue3 來做一個基本的學(xué)習(xí),以更好的應(yīng)對面試官的各種刁難問題。

在下面的這篇文章中,將從 vue2 的基礎(chǔ)知識,到 vue2 的原理知識,再到 vue3 的基礎(chǔ)知識和原理知識做一個歸納和總結(jié)。同時,周一也將整理出相關(guān)的面試題,以供大家可以有一個更好的參考。

下面開始進(jìn)入本文的講解~

🎙?一、vue2.x基礎(chǔ)知識預(yù)備

在了解常見的面試題之前,需要先對 vue 的基礎(chǔ)知識有一個體系的了解。詳細(xì)見下圖👇

  • 關(guān)于以上內(nèi)容,已整理成博文,戳下方鏈接進(jìn)入學(xué)習(xí)👇

  • 原文:萬字總結(jié)vue的基本使用和高級特性,周邊插件vuex和vue-router

  • 鏈接:https://juejin.cn/post/6976040670939054093

📻二、vue2.x基礎(chǔ)知識常見面試題

基于以上知識點(diǎn),我們將其細(xì)分為面試中的常考題。詳細(xì)見下圖👇

接下來對這些題進(jìn)行一一解答。

1、請說出vue.cli項目中src目錄每個文件夾和文件的用法?

├── assets 放置靜態(tài)資源 ├── components 放組件 ├── router 定義路由的相關(guān)配置 ├── views 視圖 ├── app.vue 應(yīng)用主組件 ├── main.js 入口文件

2、vue.cli中怎樣使用自定義的組件?有遇到過哪些問題?

如何使用:

  • 在 components 目錄新建你的組件文件( smithButton.vue );
  • 在需要用的頁面中導(dǎo)入:import smithButton from '../components/smithButton.vue';
  • 注入到 vue 的子組件的 components 屬性上,components:{smithButton}
  • 在 template 視圖 view 中使用;
  • 流程:創(chuàng)建組件→導(dǎo)入組件→注入組件→使用組件

會遇到的問題:

smithButton 命名,使用的時候需要用 smith-button ,在創(chuàng)建時常用到駝峰命名,但在使用時需把駝峰轉(zhuǎn)換為 - 表示;

vue 組件解決什么問題?

vue 組件可以提升整個項目的開發(fā)效率。能夠頁面抽象成多個相對獨(dú)立的模塊,解決了我們傳統(tǒng)項目開發(fā)效率低、難維護(hù)、復(fù)用性等等問題。

3、v-show和v-if的區(qū)別

  • v-show 通過 css 中的 display 來控制顯示和隱藏;
  • v-if 組件是真正的渲染和銷毀,而不是顯示和隱藏;
  • 當(dāng)頻繁切換顯示狀態(tài)時,用 v-show ,否則用 v-if 。

4、為何v-for中要用key

  • 必須使用 key ,且不能是 index 和 random ;
  • 原因在于,在 vue 的 diff 算法中,通過對 tag 和 key 來判斷是否為相同節(jié)點(diǎn) sameNode ,如果是相同節(jié)點(diǎn),則會盡可能的復(fù)用原有的 DOM 節(jié)點(diǎn)。
  • 使用 key 的好處是:減少渲染次數(shù),提升渲染性能。

5、描述Vue組件生命周期

(1)單組件生命周期

一般來說,組件生命周期的執(zhí)行順序為:掛載階段 → 更新階段 → 銷毀階段。下面給出常用組件生命周期的解析。

生命周期鉤子介紹
beforeCreate在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用。
created頁面還沒有渲染,但是vue的實例已經(jīng)初始化結(jié)束。
beforeMount在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用。
mounted頁面已經(jīng)渲染完畢。
beforeUpdate數(shù)據(jù)更新時調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補(bǔ)丁之前。你可以在這個鉤子中進(jìn)一步地更改狀態(tài),這不會觸發(fā)附加的重渲染過程。
updated由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁,在這之后會調(diào)用該鉤子。當(dāng)這個鉤子被調(diào)用時,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作。
activatedkeep-alive 組件激活時調(diào)用。
deactivatedkeep-alive 組件停用時調(diào)用。
beforeDestroy實例銷毀之前調(diào)用。在這一步,實例仍然完全可用。常用場景有: 自定義事件的綁定要解除、setTimeout等定時任務(wù)需要銷毀、自己綁定的window或者document事件需要銷毀。
destroyedVue 實例銷毀后調(diào)用。調(diào)用后,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀。

(2)父子組件生命周期關(guān)系

加載渲染過程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子組件更新過程

父beforeUpdate->子beforeUpdate->子updated->父updated

父組件更新過程

父beforeUpdate->父updated

銷毀過程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

6、Vue組件如何通訊(常見)

vue 組件常見的通訊方式有以下三種:

  • 父子組件 props 和 this.$emit ;
  • 自定義事件 event.$no 、 event.$off 和 event.$emit ;
  • vuex 。

7、描述組件渲染和更新的過程

關(guān)于組件的渲染和更新過程,需要了解以下這張圖。大家可以從 1-6 依次按順序地對下圖的整個過程進(jìn)行細(xì)化和解讀。

8、vue如何處理刷新數(shù)據(jù)不丟失

  • 對 vuex 進(jìn)行配置,將 vuex 的狀態(tài)儲存到 localStorage 中;
  • 在頁面加載時讀取 localStorage 里的狀態(tài)信息;
  • 在頁面刷新時將 vuex 里的信息保存到 localStorage 里;
  • 在頁面中將 vuex 里的信息使用 computed 接收。

9、雙向數(shù)據(jù)綁定 v-model 的實現(xiàn)原理

  • input 元素的 value = this.name ;

  • 綁定 input 事件 this.name = $event.target.value ;

  • data 更新后觸發(fā)重新渲染 re-render ;

  • 最核心問題:了解 v-model 在模板編譯之后,產(chǎn)生的內(nèi)容是什么。

10、computed 有何特點(diǎn)

  • 具有緩存功能,當(dāng) data 不變時不會進(jìn)行計算;

  • 有效地提高性能

11、為何組件data必須是一個函數(shù)

  • export 看似是一個對象,但是 .vue 文件編譯出來后是一個類;

  • 在每一個地方( data , method ……)等等進(jìn)行使用就是對 class 進(jìn)行實例化;

  • 我們在實例化的時候執(zhí)行 data ;

  • 如果這個 data 不是函數(shù)的話,那每一個組件的實例數(shù)據(jù)就都一樣了,就共享了;

  • 因此需要讓它在閉包之中。

12、ajax請求應(yīng)該放在哪個生命周期

  • mounted 表示整個渲染完成, dom 也加載完成,因此 ajax 請求應(yīng)該放在 mounted 生命周期中;

  • 本質(zhì)上 js 是單線程的,并且 ajax 是異步獲取數(shù)據(jù),是異步加載的一個機(jī)制;

  • 如果將其放在 mounted 之前是沒有用的,這樣做只會讓邏輯更加混亂;

  • 原因在于,如果在 mounted 之前放 ajax 請求,那么這個時候 js 還沒有渲染完成。且又因為 ajax 請求的數(shù)據(jù)還是異步的,因此即使是在 mounted 之前也不能加載,也不會有提前加載的效果。

13、如何將組件所有props傳遞給子組件?

  • 父組件通過 $props 的而方式將自己的屬性傳遞給子組件;

  • 之后子組件通過 <User v-bind = "$props" /> 這種方式去接收父組件傳遞過來的參數(shù)。

  • 注: 細(xì)節(jié)知識點(diǎn),優(yōu)先級不高

14、如何自己實現(xiàn)v-model

第一步,我們先定義一個子組件,名字叫 CustomVModel.vue ,具體代碼如下:

<template><!-- $emit是子組件往父組件傳遞數(shù)據(jù) --><input type="text":value="text1"@input="$emit('change1', $event.target.value)"><!--1. 上面的 input 使用了 :value 來綁定數(shù)據(jù),而不是使用 v-model2. 上面的 change1 和 model.event 要對應(yīng)起來3. 上面的 text1 與下面props的 text1 屬性對應(yīng)起來--> </template><script> export default {model: {prop: 'text1', // 對應(yīng)下面 props 的 text1event: 'change1'},props: {text1: String,default() {return ''}} } </script>

第二步,我們在父組件中使用上面的這個子組件:

<template><div><p>vue 高級特性</p><hr><!-- 自定義 v-model --><p>{{name}}</p><CustomVModel v-model="name"/></div> </template><script> import CustomVModel from './CustomVModel'export default {components: {CustomVModel},data() {return {name: 'Monday'}} } </script>

通過上面的代碼我們可以發(fā)現(xiàn),通過綁定 value 屬性和 input 事件這兩個語法糖,最終實現(xiàn)數(shù)據(jù)的雙向綁定。

此時我們看下瀏覽器的顯示效果。

通過上圖我們自己發(fā)現(xiàn),結(jié)果跟實際的 v-model 結(jié)果是一樣的。至此,我們就實現(xiàn)了自定義的 v-model ,以此來操作數(shù)據(jù)的雙向綁定

15、多個組件有相同的邏輯,如何抽離?

  • 在 vue2.x 中,當(dāng)多個組件有相同的邏輯時,可以使用 mixin 來進(jìn)行邏輯抽離;

  • 值得注意的是, mixin 存在有以下問題:

    • 變量來源不明確,不利于閱讀。
    • 多個 mixin 可能會造成命名沖突
    • mixin 和組件可能出現(xiàn)多對多的關(guān)系,復(fù)雜度較高。
  • 因此,要慎用 mixin ,且 vue3.x 已經(jīng)出了 Composition API ,來解決 vue2.x 中存在的這些問題。

16、何時要使用異步組件

  • 當(dāng)加載大組件時,需要用到異步組件;

  • 當(dāng) vue-router 路由要進(jìn)行異步加載時,需要用到異步組件;

  • 異步組件可以達(dá)到優(yōu)化性能的效果。

17、何時使用keep-alive

  • keep-alive 可以緩存組件,使得組件不需要重復(fù)渲染

  • 比如像多個靜態(tài) tab 頁的切換;

  • keep-alive 可以達(dá)到優(yōu)化性能的效果。

18、何時需要使用beforeDestory

  • 當(dāng)解綁自定義事件 event.$off 時,需使用 beforeDestory 來對事件進(jìn)行銷毀操作;

  • 當(dāng)使用定時器綁定時間時,在定時器操作結(jié)束時,需要清除定時器

  • 解綁自定義的 DOM 事件,如 window scroll 等,需要在 beforeDestory 生命周期來對其進(jìn)行事件解綁。

注意: 如果以上三者不做的話,很容易造成內(nèi)存泄漏

19、什么是作用域插槽

  • 父組件模板的所有東西只會在父級作用域內(nèi)編譯;
  • 子組件模板的所有東西只會在子集作用域內(nèi)編譯;
  • 而作用域插槽想解決的問題就是,讓父組件可以訪問到子組件的數(shù)據(jù)

20、vuex中action和mutation有何區(qū)別

  • action 中可以處理異步, mutation 不可以;

  • mutation 做原子操作,即做一個操作,比較原子的;

  • action 可以整合多個 mutation ,可以理解為整理多個原子操作的集合。

21、vue-router常用的路由模式

  • hash 默認(rèn)

  • H5 history (需要服務(wù)端支持)

  • 已將路由模式整理成博客,具體戳下方鏈接👇

  • 原文:淺談前端路由原理

  • 鏈接:https://juejin.cn/post/6993840419041706014

22、如何配置vue-router異步加載

  • 在 vue-router 中,使用 import 來實現(xiàn)異步加載。

23、scope是怎么實現(xiàn)的

(1)scoped的實現(xiàn)原理:

  • 給 DOM 節(jié)點(diǎn)加一個不重復(fù)的屬性 data-v-5db9451a 來標(biāo)志唯一性。
  • 如果組件內(nèi)部還有組件,只會給最外層的組件里的標(biāo)簽加上唯一屬性字段,不影響組件內(nèi)部引用的組件。

(2)vue中scoped的作用:

  • 實現(xiàn)組件的私有化,當(dāng)前 style 樣式屬性只屬于當(dāng)前模塊,不污染全局。
  • 但是當(dāng)我們使用公共組件的時候會造成很多困難。

(3)謹(jǐn)慎使用:

  • 父組件無 scoped 屬性,子組件帶有 scoped ,父組件是無法操作子組件的。
  • 父組件有 scoped 屬性,子組件無 scoped 。父組件也無法設(shè)置子組件樣式。因為父組件的所有標(biāo)簽都會帶有 data-v-5db9451a 唯一標(biāo)志,但子組件不會帶有這個唯一標(biāo)志屬性。
  • 父子組件都有,同理也無法設(shè)置樣式,更改起來增加代碼量。

24、vue常用性能優(yōu)化方式

  • 合理使用 v-show 和 v-if
  • 合理使用 computed
  • v-for 時加 key ,以及避免和 v-if 同時使用
  • 自定義事件、 DOM 事件及時銷毀
  • 合理使用異步組件
  • 合理使用 keep-alive
  • data 層級不要太深,盡量扁平
  • 使用 vue-loader 在開發(fā)環(huán)境做模板編譯(預(yù)編譯)
  • 合理使用 keep-alive
  • webpack 層面的優(yōu)化
  • 使用 SSR

📟三、vue2.x原理知識預(yù)備

在了解常見的面試題之前,需要先對 vue2.x 的原理知識有一個體系的了解。詳細(xì)見下圖👇

  • 關(guān)于以上內(nèi)容,已整理成博文,戳下方鏈接進(jìn)入學(xué)習(xí)👇

  • 原文1:手把手教你剖析vue響應(yīng)式原理,監(jiān)聽數(shù)據(jù)不再迷茫

  • 鏈接1:https://juejin.cn/post/6978278417951096839

  • 原文2:面試中的網(wǎng)紅虛擬DOM,你知多少呢?深入解讀diff算法

  • 鏈接2:https://juejin.cn/post/6978621084862005285

  • 原文3:模板編譯template的背后,究竟發(fā)生了什么事?帶你了解template的紙短情長

  • 鏈接3:https://juejin.cn/post/6978965732633608222

📠四、vue原理知識常見面試題

基于以上知識點(diǎn),我們將其細(xì)分為面試中的常考題。詳細(xì)見下圖👇

接下來對這些題目進(jìn)行一一解答。

1、對MVVM的理解

所謂 MVVM ,即 Model-View-ViewModel

View視圖 ,也就是 DOM 。

Model模型 ,可以理解為 Vue 中組件里面的 data 。

那么這兩者之間,就通過 ViewModel 來做關(guān)聯(lián)。而 ViewModel 可以做的事情有很多,比如說像監(jiān)聽事件,監(jiān)聽指令等。當(dāng) Model 層的數(shù)據(jù)發(fā)生修改時,就可以通過 ViewModel ,來把數(shù)據(jù)渲染到 View 視圖層上。反之,當(dāng) View 層觸發(fā) DOM 事件時,就可以通過 ViewModel ,從而使得 Model 層實現(xiàn)數(shù)據(jù)的修改。

這就是 Vue 中的數(shù)據(jù)驅(qū)動視圖,通過修改 Model 層的數(shù)據(jù),來驅(qū)動到 View 的視圖中來。

2、監(jiān)聽data變化的核心 API 是什么

  • 所謂 vue 的響應(yīng)式,即組件 data 的數(shù)據(jù)一旦變化,就會立刻觸發(fā)視圖的更新。實現(xiàn)數(shù)據(jù)驅(qū)動視圖的第一步,需要了解實現(xiàn)響應(yīng)式的一個核心 API ,即 Object.defineProperty 。
  • 通過 Object.defineProperty ,我們可以實現(xiàn)對數(shù)據(jù)進(jìn)行 get 和 set 操作,即獲取數(shù)據(jù)修改數(shù)據(jù)的操作,從而達(dá)到對數(shù)據(jù)進(jìn)行響應(yīng)式的監(jiān)聽。

3、vue如何監(jiān)聽數(shù)組變化

要想讓 Object.defineProperty() 這個 API 擁有監(jiān)聽數(shù)組的能力,我們可以這么做。具體代碼如下:

// 觸發(fā)更新視圖 function updateView() {console.log('視圖更新') }// 重新定義數(shù)組原型 const oldArrayProperty = Array.prototype // 創(chuàng)建新對象,原型指向 oldArrayProperty ,再擴(kuò)展新的方法不會影響原型 const arrProto = Object.create(oldArrayProperty); ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {arrProto[methodName] = function () {updateView() // 觸發(fā)視圖更新oldArrayProperty[methodName].call(this, ...arguments)// Array.prototype.push.call(this, ...arguments)} })// 重新定義屬性,監(jiān)聽起來 function defineReactive(target, key, value) {// 深度監(jiān)聽observer(value)// 核心 APIObject.defineProperty(target, key, {get() {return value},set(newValue) {if (newValue !== value) {// 深度監(jiān)聽observer(newValue)// 設(shè)置新值// 注意,value 一直在閉包中,此處設(shè)置完之后,再 get 時也是會獲取最新的值value = newValue// 觸發(fā)更新視圖updateView()}}}) }// 監(jiān)聽對象屬性 function observer(target) {if (typeof target !== 'object' || target === null) {// 不是對象或數(shù)組return target}// 污染全局的 Array 原型(如果直接定義在這里面,會直接污染全局)// Array.prototype.push = function () {// updateView()// ...// }if (Array.isArray(target)) {target.__proto__ = arrProto}// 重新定義各個屬性(for in 也可以遍歷數(shù)組)for (let key in target) {defineReactive(target, key, target[key])} }// 準(zhǔn)備數(shù)據(jù) const data = {name: 'monday',age: 20,info: {address: '深圳' // 需要深度監(jiān)聽},nums: ['打籃球', '出來玩', '打乒乓球'] }// 監(jiān)聽數(shù)據(jù) observer(data)// 測試 data.info.address = '上海' // 深度監(jiān)聽 data.nums.push('神游') // 監(jiān)聽數(shù)組復(fù)制代碼

此時瀏覽器的打印效果如下:

我們可以看到,兩個數(shù)據(jù)對應(yīng)的視圖都更新了。通過對數(shù)組原型的重新定義,我們就讓 Object.defineProperty() 實現(xiàn)了監(jiān)聽數(shù)組的能力。

4、請描述響應(yīng)式原理


響應(yīng)式原理概述:

  • 任何一個 Vue 組件都會生成一個 render 函數(shù)。
  • 之后 render 函數(shù)會生成一個 vnode 。
  • 同時,在執(zhí)行 render 函數(shù)的時候會觸發(fā) data 里面的 getter ,觸發(fā)后則會生成依賴。
  • 所謂依賴,就是在 data 觸發(fā)到哪個變量,就會將哪一個變量觀察起來。
  • 之后,需要查看觸發(fā)到的這個變量是否是之前作為依賴被觀察起來的,如果是,則觸發(fā) setter 進(jìn)行數(shù)據(jù)修改;如果不是,則直接進(jìn)行監(jiān)聽操作;
  • 最后,如果確定是之前作為依賴被重新觀察起來的,那就執(zhí)行 re-render 重新渲染操作,并且進(jìn)行 patch(vnode, newVnode) 。

5、請用vnode描述一個DOM結(jié)構(gòu)

根據(jù)下方的 html 代碼,用 v-node 模擬出該 html 代碼的 DOM 結(jié)構(gòu)。

html代碼:

<div id="div1" class="container"><p>vdom</p><ul style="font-size:20px;"><li>a</li></ul> </div> 復(fù)制代碼

用JS模擬出以上代碼的DOM結(jié)構(gòu):

{tag: 'div',props:{className: 'container',id: 'div1'},children: [{tag: 'p',chindren: 'vdom'},{tag: 'ul',props:{ style: 'font-size: 20px' },children: [{tag: 'li',children: 'a'}// ....]}] }

6、diff算法的時間復(fù)雜度

  • 樹的時間復(fù)雜度是 O(n3) ,因此,我們就想辦法,優(yōu)化其時間復(fù)雜度從O(n3)到O(n),以達(dá)到操作 vdom 節(jié)點(diǎn),那這個優(yōu)化過程其實我們所說的 diff 算法。
  • 所以, diff 算法的時間復(fù)雜度為 O(n) 。

7、簡述diff算法過程

  • 首先,對比節(jié)點(diǎn)本身,要先判斷是否為同一節(jié)點(diǎn),如果不為相同節(jié)點(diǎn),則刪除該節(jié)點(diǎn)重新創(chuàng)建節(jié)點(diǎn)進(jìn)行替換;
  • 如果為相同節(jié)點(diǎn)時,進(jìn)行 patchVnode ,判斷如何對該節(jié)點(diǎn)的子節(jié)點(diǎn)進(jìn)行處理,先判斷一方有子節(jié)點(diǎn)一方?jīng)]有子節(jié)點(diǎn)的情況(如果新的 children 沒有子節(jié)點(diǎn),則將舊的子節(jié)點(diǎn)移除);
  • 比較如果都有子節(jié)點(diǎn),則進(jìn)行 updateChildren ,判斷如何對這些新老節(jié)點(diǎn)的子節(jié)點(diǎn)進(jìn)行操作( diff 核心)。
  • 匹配時,找到相同的子節(jié)點(diǎn),遞歸比較子節(jié)點(diǎn)。

注意: 在 diff 中,只對同層的子節(jié)點(diǎn)進(jìn)行比較,放棄跨級的節(jié)點(diǎn)比較,使得時間復(fù)雜從 O(n^3) 降低值 O(n) ,也就是說,只有當(dāng)新舊 children 都為多個子節(jié)點(diǎn)時才需要用核心的 diff 算法進(jìn)行同層級比較。

8、vue模板編譯的原理是什么

  • vue 在進(jìn)行模板編譯之后,會先轉(zhuǎn)化成一個 render 函數(shù),之后繼續(xù)執(zhí)行 render 函數(shù),執(zhí)行完成之后返回一個 vnode ;
  • 在得到 vnode 之后,基于 vnode 的基礎(chǔ)上,再執(zhí)行 patch 和 diff 。

9、vue為何是異步渲染,$nextTick有何用?

  • vue 是組件級更新,一旦當(dāng)前組件里的數(shù)據(jù)變了,那么它就會去更新這個組件。
  • 但是試想一下,如果當(dāng)數(shù)據(jù)更改一次,組件就要去重新渲染一次,這樣對性能來說都是不太友好的。
  • 因此,為了防止數(shù)據(jù)一更新就更新組件,所以需要異步渲染來處理。
  • 而異步渲染的核心的方法就是 nextTick , $nextTick 可以在 DOM 更新完之后,再觸發(fā)回調(diào)

10、SPA單頁面應(yīng)用是什么?

SPA,即單頁面應(yīng)用(Single Page Application)。所謂單頁 Web 應(yīng)用,就是只有一張 Web 頁面的應(yīng)用。單頁應(yīng)用程序 (SPA) 是加載單個 HTML 頁面并在用戶與應(yīng)用程序交互時動態(tài)更新該頁面的 Web 應(yīng)用程序。瀏覽器一開始會加載必需的 HTML 、 CSS 和 JavaScript ,所有的操作都在這張頁面上完成,都由 JavaScript 來控制。

現(xiàn)如今,為了配合單頁面 Web 應(yīng)用快速發(fā)展的節(jié)奏,各類前端組件化技術(shù)棧層出不窮。近幾年來,通過不斷的版本迭代, vue 和 react 兩大技術(shù)棧脫穎而出,成為當(dāng)下最受歡迎的兩大技術(shù)棧。

11、hash和history的區(qū)別是什么?

(1)hash

  • hash變化會觸發(fā)網(wǎng)頁跳轉(zhuǎn),即瀏覽器的前進(jìn)和后退。
  • hash 可以改變 url ,但是不會觸發(fā)頁面重新加載(hash的改變是記錄在 window.history 中),即不會刷新頁面。也就是說,所有頁面的跳轉(zhuǎn)都是在客戶端進(jìn)行操作。因此,這并不算是一次 http 請求,所以這種模式不利于 SEO 優(yōu)化。hash 只能修改 # 后面的部分,所以只能跳轉(zhuǎn)到與當(dāng)前 url 同文檔的 url 。
  • hash 通過 window.onhashchange 的方式,來監(jiān)聽 hash 的改變,借此實現(xiàn)無刷新跳轉(zhuǎn)的功能。
  • hash 永遠(yuǎn)不會提交到 server 端(可以理解為只在前端自生自滅)。

(2)history

  • 新的 url 可以是與當(dāng)前 url 同源的任意 url ,也可以是與當(dāng)前 url 一樣的地址,但是這樣會導(dǎo)致的一個問題是,會把重復(fù)的這一次操作記錄到棧當(dāng)中。
  • 通過 history.state ,添加任意類型的數(shù)據(jù)到記錄中。
  • 可以額外設(shè)置 title 屬性,以便后續(xù)使用。
  • 通過 pushState 、 replaceState 來實現(xiàn)無刷新跳轉(zhuǎn)的功能。
  • 使用 history 模式時,在對當(dāng)前的頁面進(jìn)行刷新時,此時瀏覽器會重新發(fā)起請求。如果 nginx 沒有匹配得到當(dāng)前的 url ,就會出現(xiàn) 404 的頁面。
  • 而對于 hash 模式來說, 它雖然看著是改變了 url ,但不會被包括在 http 請求中。所以,它算是被用來指導(dǎo)瀏覽器的動作,并不影響服務(wù)器端。因此,改變 hash 并沒有真正地改變 url ,所以頁面路徑還是之前的路徑, nginx 也就不會攔截。
  • 因此,在使用 history 模式時,需要通過服務(wù)端來允許地址可訪問,如果沒有設(shè)置,就很容易導(dǎo)致出現(xiàn) 404 的局面。

12、hash和history兩者的選擇

  • to B 的系統(tǒng)推薦用 hash ,相對簡單且容易使用,且因為 hash 對 url 規(guī)范不敏感;
  • to C 的系統(tǒng),可以考慮選擇 H5 history ,但是需要服務(wù)端支持
  • 能先用簡單的,就別用復(fù)雜的,要考慮成本和收益

🖨?五、vue3.x知識預(yù)備

關(guān)于 vue3 模塊,我將把基礎(chǔ)知識原理的內(nèi)容結(jié)合在一起進(jìn)行整理。詳細(xì)見下圖👇

  • 關(guān)于以上內(nèi)容,已整理成博文,戳下方鏈接進(jìn)入學(xué)習(xí)👇

  • 原文1: 一文了解vue3基礎(chǔ)新特性

  • 鏈接1: https://juejin.cn/post/6976400439793172487

  • 原文2: 敲黑板!vue3重點(diǎn)!一文了解Composition API新特性:ref、toRef、toRefs

  • 鏈接2: https://juejin.cn/post/6976679225239535629

  • 原文3: 一文get一波 vue3.x 進(jìn)階新特性

  • 鏈接3: https://juejin.cn/post/6976040670939054093

  • 原文4: vue2的響應(yīng)式原理學(xué)“廢”了嗎?繼續(xù)觀摩vue3響應(yīng)式原理Proxy

  • 鏈接4: https://juejin.cn/post/6979368550225936392

??六、vue3.x常見面試題

基于以上知識點(diǎn),我們將其細(xì)分為面試中的常考題。詳細(xì)見下圖👇

接下來對這些題進(jìn)行一一解答。

1、vue3和vue2有什么優(yōu)勢?

  • vue3 比 vue2 來說,性能上更好代碼體積更小,并且有更好的ts支持
  • 同時,更為突出的特點(diǎn)是, vue3 有更好的代碼組織能力,有更好的邏輯抽離能力,并且還有更多各式各樣的新功能
  • 其中尤為突出的就是大家平常耳熟能詳?shù)?Composition API 和 Options API 。

2、描述vue3生命周期

以下給出 Vue2 與 Vue3 生命周期的對比。

Vue2生命周期(Options API)Vue3生命周期(Composition API)含義
beforeCreatesetup在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用
createdsetup頁面還沒有渲染,但是vue的實例已經(jīng)初始化結(jié)束。
beforeMountonBeforeMount在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用。
mountedonMounted頁面已經(jīng)渲染完畢。
beforeUpdateonBeforeUpdate數(shù)據(jù)更新時調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補(bǔ)丁之前。你可以在這個鉤子中進(jìn)一步地更改狀態(tài),這不會觸發(fā)附加的重渲染過程。
updatedonUpdated由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁,在這之后會調(diào)用該鉤子。當(dāng)這個鉤子被調(diào)用時,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作。
beforeDestoryonBeforeUnmount實例銷毀之前調(diào)用。在這一步,實例仍然完全可用。
destroyonUnmountedVue 實例銷毀后調(diào)用。

3、如何看待Composition API和Options API

對于 Composition API 和 Options API 的使用,主要有以下幾點(diǎn)建議:

  • 兩者不建議共用,不然很容易引起混亂;
  • 對于小型項目、或者業(yè)務(wù)邏輯比較簡單的項目,建議使用 Options API ;
  • 對于中大型項目、或者邏輯比較復(fù)雜的項目,建議使用 Composition API ,相較于 Options API 來說, Composition API 對大型項目更好一些,邏輯的抽離,代碼的復(fù)用,使得大型項目得以更好的維護(hù)。

4、如何理解ref、toRef和toRefs

(1)ref是什么

  • ref 是可以生成 值類型(即基本數(shù)據(jù)類型) 的響應(yīng)式數(shù)據(jù);
  • ref 可以用于模板reactive
  • ref 通過 .value 來修改值(一定要記得加上 .value );
  • ref 不僅可以用于響應(yīng)式,還可以用于模板的 DOM 元素。

(2)toRef是什么

  • toRef 可以響應(yīng)對象 Object ,其針對的是某一個響應(yīng)式對象( reactive 封裝)的屬性 prop 。

  • toRef 和對象 Object 兩者保持引用關(guān)系,即一個改完另外一個也跟著改。

  • toRef 如果用于普通對象(非響應(yīng)式對象),產(chǎn)出的結(jié)果不具備響應(yīng)式。如下代碼所示:

//普通對象 const state = {age: 20,name: 'monday' } //響應(yīng)式對象 const state = reactive({age: 20,name: 'monday' })

(3)toRefs是什么

  • 與 toRef 不一樣的是, toRefs 是針對整個對象的所有屬性,目標(biāo)在于將響應(yīng)式對象( reactive 封裝)轉(zhuǎn)換為普通對象。
  • 普通對象里的每一個屬性 prop 都對應(yīng)一個 ref 。
  • toRefs 和對象 Object 兩者保持引用關(guān)系,即一個改完另外一個也跟著改。

5、vue3升級了哪些重要的功能?

  • createApp
  • emits(父子組件間的通信)
  • 多事件處理
  • Fragment
  • 移除 .sync
  • 異步組件
  • 移除filter
  • Teleport
  • Suspense

6、Composition API如何實現(xiàn)代碼的邏輯復(fù)用?

  • composition API 通過把代碼的邏輯抽離出來進(jìn)行封裝,并把封裝的內(nèi)容直接引用到生命周期里面,已達(dá)到代碼的邏輯復(fù)用效果。

7、Vue3如何實現(xiàn)響應(yīng)式?

  • 利用 reactive 注冊響應(yīng)式對象,對函數(shù)返回值進(jìn)行操作。
  • 利用 Proxy 劫持?jǐn)?shù)據(jù)的 get , set , deleteProperty , has , own 。
  • 利用 WeakMap , Map , Set 來實現(xiàn)依賴收集。
  • 缺點(diǎn): 使用大量 ES6 新增特性,舊版本瀏覽器兼容性差。

8、Watch和watchEffect的區(qū)別是什么?

  • 兩者都可以監(jiān)聽 data 屬性變化;
  • watch 需要明確監(jiān)聽哪個屬性
  • 而 watchEffect 會根據(jù)其中的屬性,自動監(jiān)聽其變化。

9、setup中如何獲取組件實例?

在 vue2 中, Options API 可以使用 this 來獲取組件的實例,但是到現(xiàn)在的 vue3 ,已經(jīng)被摒棄掉了。在 setup 和其他 Composition API 中沒有 this ,但是它提供了一個 getCurrentInstance 來獲取當(dāng)前的實例。

10、vue3為何比vue2快?

  • Proxy響應(yīng)式
  • PatchFlag
  • hoistStatic
  • cacheHandler
  • SSR優(yōu)化
  • tree-shaking

11、vite是什么?

  • vite 是一個前端的打包工具,是 vue 作者發(fā)起的一個項目;
  • vite 借助 vue 的影響力,發(fā)展較快,和 webpack 有著一定的競爭關(guān)系;
  • 優(yōu)勢: vite 使得程序在開發(fā)環(huán)境下無需打包,且啟動非常快速。

12、Composition API和React hooks的對比

  • 前者 setup 只會被調(diào)用一次,而后者函數(shù)會被多次調(diào)用。
  • 前者無需 useMemo和 useCallback (即緩存數(shù)據(jù)和緩存函數(shù)),因為 setup 只調(diào)用一次。
  • 前者無需顧慮調(diào)用順序,而后者需要保證 hooks 的順序一致。
  • 前者 reactive+ref 比后者的 useState ,要難理解。

📸七、結(jié)束語

從 vue2.x 的基礎(chǔ)知識,再到 vue2.x 的原理知識,最后到 vue3.x 的新特性和原理知識學(xué)習(xí),全文貫穿著 vue 的知識要點(diǎn)及相關(guān)知識點(diǎn)所涉及到的一些面試題。

最后,關(guān)于這部分內(nèi)容已整理成 PDF ,獲取方式放在彩蛋里面,有需要的小伙伴自取o!

🐣彩蛋 One More Thing

🏷?往期推薦

vue2.x 和 vue3.x 的原理學(xué)習(xí),累計博文輸出 11 篇,以下是相關(guān)專欄文章~

  • vue.js基礎(chǔ)知識👉基礎(chǔ)知識專欄傳送門
  • vue.js原理知識👉原理知識專欄傳送門

面試專欄 pdf 版本:

  • 微信搜索 星期一研究室 并關(guān)注,回復(fù)關(guān)鍵詞 vue面試pdf 獲取相關(guān)資料~

  • 回復(fù) 面試大全pdf 可獲取全系列資料!

更新地址:

  • offer來了面試專欄

🏷?番外篇

  • 如果這篇文章對你有用,記得留個腳印jio再走哦~
  • 以上就是本文的全部內(nèi)容!我們下期見!👋👋👋

總結(jié)

以上是生活随笔為你收集整理的「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。