組件通信相關(guān)問題
組件通信方式有哪些沼死?
父子組件通信:
props 和 event刑棵、v-model声登、 .sync、 ref哈街、 $parent 和 $children
非父子組件通信:
$attr 和 l i s t e n e r s 留瞳、 p r o v i d e 和 i n j e c t 、 e v e n t b u s 骚秦、 通 過 根 實 例 listeners她倘、 provide 和 inject璧微、eventbus、通過根實例listeners硬梁、provide和inject前硫、eventbus、通過根實例root訪問荧止、vuex屹电、dispatch 和 brodcast
通信方式屬于較基礎(chǔ)的面試題,具體的可參考我的文章—— vue 組件通信看這篇就夠了
子組件為什么不可以修改父組件傳遞的Prop跃巡?
Vue提倡單向數(shù)據(jù)流,即父級 props 的更新會流向子組件,但是反過來則不行危号。這是為了防止意外的改變父組件狀態(tài),使得應(yīng)用的數(shù)據(jù)流變得難以理解素邪。如果破壞了單向數(shù)據(jù)流外莲,當(dāng)應(yīng)用復(fù)雜時,debug 的成本會非常高娘香。
v-model是如何實現(xiàn)雙向綁定的苍狰?
v-model 是用來在表單控件或者組件上創(chuàng)建雙向綁定的,他的本質(zhì)是 v-bind 和 v-on 的語法糖烘绽,在一個組件上使用 v-model淋昭,默認(rèn)會為組件綁定名為 value 的 prop 和名為 input 的事件。
文章—— vue 組件通信看這篇就夠了 中也有其詳細(xì)介紹
Vuex和單純的全局對象有什么區(qū)別安接?
Vuex和全局對象主要有兩大區(qū)別:
Vuex 的狀態(tài)存儲是響應(yīng)式的翔忽。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時候,若 store 中的狀態(tài)發(fā)生變化盏檐,那么相應(yīng)的組件也會相應(yīng)地得到高效更新歇式。
不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation胡野。這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化材失,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。
為什么 Vuex 的 mutation 中不能做異步操作硫豆?
Vuex中所有的狀態(tài)更新的唯一途徑都是mutation龙巨,異步操作通過 Action 來提交 mutation實現(xiàn),這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化熊响,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用旨别。
每個mutation執(zhí)行完成后都會對應(yīng)到一個新的狀態(tài)變更,這樣devtools就可以打個快照存下來汗茄,然后就可以實現(xiàn) time-travel 了秸弛。如果mutation支持異步操作,就沒有辦法知道狀態(tài)是何時更新的,無法很好的進(jìn)行狀態(tài)的追蹤递览,給調(diào)試帶來困難叼屠。
參考尤大大回答:
www.zhihu.com/question/48…
聲明周期相關(guān)問題
vue組件有哪些聲明周期鉤子?
beforeCreate绞铃、created环鲤、beforeMount、mounted憎兽、beforeUpdate冷离、updated、beforeDestroy纯命、destroyed西剥。
有自己獨立的鉤子函數(shù) activated 和 deactivated。
Vue 的父組件和子組件生命周期鉤子執(zhí)行順序是什么亿汞?
渲染過程:
父組件掛載完成一定是等子組件都掛載完成后瞭空,才算是父組件掛載完,所以父組件的mounted在子組件mouted之后
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
子組件更新過程:
影響到父組件:
父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
不影響父組件:
子beforeUpdate -> 子updated
父組件更新過程:
影響到子組件:
父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
不影響子組件:
父beforeUpdate -> 父updated
銷毀過程:
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
看起來很多好像很難記憶疗我,其實只要理解了咆畏,不管是哪種情況,都一定是父組件等待子組件完成后吴裤,才會執(zhí)行自己對應(yīng)完成的鉤子旧找,就可以很容易記住。
相關(guān)屬性的作用 & 相似屬性對比
v-show 和 v-if 有哪些區(qū)別麦牺?
v-if 會在切換過程中對條件塊的事件監(jiān)聽器和子組件進(jìn)行銷毀和重建钮蛛,如果初始條件是false,則什么都不做剖膳,直到條件第一次為true時才開始渲染模塊魏颓。
v-show 只是基于css進(jìn)行切換,不管初始條件是什么吱晒,都會渲染甸饱。
所以,v-if 切換的開銷更大仑濒,而 v-show 初始化渲染開銷更大叹话,在需要頻繁切換,或者切換的部分dom很復(fù)雜時躏精,使用 v-show 更合適渣刷。渲染后很少切換的則使用 v-if 更合適鹦肿。
computed 和 watch 有什么區(qū)別矗烛?
computed 計算屬性,是依賴其他屬性的計算值,并且有緩存瞭吃,只有當(dāng)依賴的值變化時才會更新碌嘀。
watch 是在監(jiān)聽的屬性發(fā)生變化時,在回調(diào)中執(zhí)行一些邏輯歪架。
所以股冗,computed 適合在模板渲染中,某個值是依賴了其他的響應(yīng)式對象甚至是計算屬性計算而來和蚪,而 watch 適合監(jiān)聽某個值的變化去完成一段復(fù)雜的業(yè)務(wù)邏輯止状。
computed vs methods
計算屬性是基于他們的響應(yīng)式依賴進(jìn)行緩存的,只有在依賴發(fā)生變化時攒霹,才會計算求值怯疤,而使用 methods,每次都會執(zhí)行相應(yīng)的方法催束。
keep-alive 的作用是什么集峦?
keep-alive 可以在組件切換時,保存其包裹的組件的狀態(tài)抠刺,使其不被銷毀塔淤,防止多次渲染。
其擁有兩個獨立的生命周期鉤子函數(shù) actived 和 deactived速妖,使用 keep-alive 包裹的組件在切換時不會被銷毀高蜂,而是緩存到內(nèi)存中并執(zhí)行 deactived 鉤子函數(shù),命中緩存渲染后會執(zhí)行 actived 鉤子函數(shù)罕容。
Vue 中 v-html 會導(dǎo)致什么問題
在網(wǎng)站上動態(tài)渲染任意 HTML妨马,很容易導(dǎo)致 XSS 攻擊。所以只能在可信內(nèi)容上使用 v-html杀赢,且永遠(yuǎn)不能用于用戶提交的內(nèi)容上烘跺。
原理分析相關(guān)題目
這部分的面試題,只看答案部分是不夠的脂崔,最好結(jié)合源碼來分析滤淳,可以有更深的理解。我在之前的文章對某些源碼做過分析的砌左,會給出鏈接脖咐。
Vue 的響應(yīng)式原理
如果面試被問到這個問題,又描述不清楚汇歹,可以直接畫出 Vue 官方文檔的這個圖屁擅,對著圖來解釋效果會更好。
Vue 的響應(yīng)式是通過 Object.defineProperty 對數(shù)據(jù)進(jìn)行劫持产弹,并結(jié)合觀察者模式實現(xiàn)派歌。
Vue 利用 Object.defineProperty 創(chuàng)建一個 observe 來劫持監(jiān)聽所有的屬性,把這些屬性全部轉(zhuǎn)為 getter 和 setter。Vue 中每個組件實例都會對應(yīng)一個 watcher 實例胶果,它會在組件渲染的過程中把使用過的數(shù)據(jù)屬性通過 getter 收集為依賴匾嘱。之后當(dāng)依賴項的 setter 觸發(fā)時,會通知 watcher早抠,從而使它關(guān)聯(lián)的組件重新渲染霎烙。
2. Object.defineProperty有哪些缺點?
這道題目也可以問成 “為什么vue3.0使用proxy實現(xiàn)響應(yīng)式蕊连?” 其實都是對Object.defineProperty 和 proxy實現(xiàn)響應(yīng)式的對比悬垃。
Object.defineProperty 只能劫持對象的屬性,而 Proxy 是直接代理對象
由于 Object.defineProperty 只能對屬性進(jìn)行劫持甘苍,需要遍歷對象的每個屬性盗忱。而 Proxy 可以直接代理對象。
Object.defineProperty 對新增屬性需要手動進(jìn)行 Observe羊赵,
由于 Object.defineProperty 劫持的是對象的屬性趟佃,所以新增屬性時,需要重新遍歷對象昧捷,對其新增屬性再使用 Object.defineProperty 進(jìn)行劫持闲昭。
也正是因為這個原因,使用 Vue 給 data 中的數(shù)組或?qū)ο笮略鰧傩詴r靡挥,需要使用 vm.$set 才能保證新增的屬性也是響應(yīng)式的序矩。
Proxy 支持13種攔截操作,這是 defineProperty 所不具有的跋破。
新標(biāo)準(zhǔn)性能紅利
Proxy 作為新標(biāo)準(zhǔn)簸淀,長遠(yuǎn)來看,JS引擎會繼續(xù)優(yōu)化 Proxy 毒返,但 getter 和 setter 基本不會再有針對性優(yōu)化租幕。
Proxy 兼容性差
目前并沒有一個完整支持 Proxy 所有攔截方法的Polyfill方案
更詳細(xì)的對比,可以查看我的文章 為什么Vue3.0不再使用defineProperty實現(xiàn)數(shù)據(jù)監(jiān)聽拧簸?
3. Vue中如何檢測數(shù)組變化劲绪?
Vue 的 Observer 對數(shù)組做了單獨的處理,對數(shù)組的方法進(jìn)行編譯盆赤,并賦值給數(shù)組屬性的 proto 屬性上贾富,因為原型鏈的機(jī)制,找到對應(yīng)的方法就不會繼續(xù)往上找了牺六。編譯方法中會對一些會增加索引的方法(push颤枪,unshift,splice)進(jìn)行手動 observe淑际。
具體同樣可以參考我的這篇文章 為什么Vue3.0不再使用defineProperty實現(xiàn)數(shù)據(jù)監(jiān)聽畏纲?扇住,里面有詳細(xì)的源碼分析。
4. 組件的 data 為什么要寫成函數(shù)形式霍骄?
Vue 的組件都是可復(fù)用的,一個組件創(chuàng)建好后淡溯,可以在多個地方復(fù)用读整,而不管復(fù)用多少次,組件內(nèi)的 data 都應(yīng)該是相互隔離咱娶,互不影響的米间,所以組件每復(fù)用一次,data 就應(yīng)該復(fù)用一次膘侮,每一處復(fù)用組件的 data 改變應(yīng)該對其他復(fù)用組件的數(shù)據(jù)不影響屈糊。
為了實現(xiàn)這樣的效果,data 就不能是單純的對象琼了,而是以一個函數(shù)返回值的形式逻锐,所以每個組件實例可以維護(hù)獨立的數(shù)據(jù)拷貝,不會相互影響雕薪。
5. nextTick是做什么用的昧诱,其原理是什么?
能回答清楚這道問題的前提,是清楚 EventLoop 過程所袁。
在下次 DOM 更新循環(huán)結(jié)束后執(zhí)行延遲回調(diào)盏档,在修改數(shù)據(jù)之后立即使用 nextTick 來獲取更新后的 DOM。
nextTick 對于 micro task 的實現(xiàn)燥爷,會先檢測是否支持 Promise蜈亩,不支持的話,直接指向 macro task前翎,而 macro task 的實現(xiàn)稚配,優(yōu)先檢測是否支持 setImmediate(高版本IE和Etage支持),不支持的再去檢測是否支持 MessageChannel港华,如果仍不支持药有,最終降級為 setTimeout 0;
默認(rèn)的情況苹丸,會先以 micro task 方式執(zhí)行愤惰,因為 micro task 可以在一次 tick 中全部執(zhí)行完畢,在一些有重繪和動畫的場景有更好的性能赘理。
但是由于 micro task 優(yōu)先級較高宦言,在某些情況下,可能會在事件冒泡過程中觸發(fā)商模,導(dǎo)致一些問題(可以參考 Vue 這個 issue:github.com/vuejs/vue/i…)奠旺,所以有些地方會強(qiáng)制使用 macro task (如 v-on)蜘澜。
注意:之所以將 nextTick 的回調(diào)函數(shù)放入到數(shù)組中一次性執(zhí)行,而不是直接在 nextTick 中執(zhí)行回調(diào)函數(shù)响疚,是為了保證在同一個tick內(nèi)多次執(zhí)行了 nextTcik鄙信,不會開啟多個異步任務(wù),而是把這些異步任務(wù)都壓成一個同步任務(wù)忿晕,在下一個tick內(nèi)執(zhí)行完畢装诡。
Vue 的模板編譯原理
vue模板的編譯過程分為3個階段:
第一步:解析
將模板字符串解析生成 AST,生成的AST 元素節(jié)點總共有 3 種類型践盼,1 為普通元素鸦采, 2 為表達(dá)式,3為純文本咕幻。
第二步:優(yōu)化語法樹
Vue 模板中并不是所有數(shù)據(jù)都是響應(yīng)式的渔伯,有很多數(shù)據(jù)是首次渲染后就永遠(yuǎn)不會變化的,那么這部分?jǐn)?shù)據(jù)生成的 DOM 也不會變化肄程,我們可以在 patch 的過程跳過對他們的比對锣吼。
此階段會深度遍歷生成的 AST 樹,檢測它的每一顆子樹是不是靜態(tài)節(jié)點蓝厌,如果是靜態(tài)節(jié)點則它們生成 DOM 永遠(yuǎn)不需要改變吐限,這對運行時對模板的更新起到極大的優(yōu)化作用。
生成代碼
const code = generate(ast, options)
復(fù)制代碼通過 generate 方法褂始,將ast生成 render 函數(shù)诸典。
更多關(guān)于 AST,Vue 模板編譯原理崎苗,以及和 AST 相關(guān)的 Babel 工作原理等狐粱,我在 掌握了AST,再也不怕被問babel胆数,vue編譯肌蜻,Prettier等原理 中做了詳細(xì)介紹。
7. v-for 中 key 的作用是什么必尼?
清晰回答這道問題蒋搜,需要先清楚 Vue 的 diff 過程,關(guān)于 diff 原理判莉,推薦一篇文章 my.oschina.net/u/3060934/b…
key 是給每個 vnode 指定的唯一 id豆挽,在同級的 vnode diff 過程中,可以根據(jù) key 快速的對比券盅,來判斷是否為相同節(jié)點帮哈,并且利用 key 的唯一性可以生成 map 來更快的獲取相應(yīng)的節(jié)點。
另外指定 key 后锰镀,就不再采用“就地復(fù)用”策略了娘侍,可以保證渲染的準(zhǔn)確性咖刃。
8. 為什么 v-for 和 v-if 不建議用在一起
當(dāng) v-for 和 v-if 處于同一個節(jié)點時,v-for 的優(yōu)先級比 v-if 更高憾筏,這意味著 v-if 將分別重復(fù)運行于每個 v-for 循環(huán)中嚎杨。如果要遍歷的數(shù)組很大,而真正要展示的數(shù)據(jù)很少時氧腰,這將造成很大的性能浪費枫浙。
這種場景建議使用 computed,先對數(shù)據(jù)進(jìn)行過濾容贝。
路由相關(guān)問題
Vue-router 導(dǎo)航守衛(wèi)有哪些
全局前置/鉤子:beforeEach自脯、beforeResolve之景、afterEach
路由獨享的守衛(wèi):beforeEnter
組件內(nèi)的守衛(wèi):beforeRouteEnter斤富、beforeRouteUpdate、beforeRouteLeave
完整的導(dǎo)航解析流程如下:
導(dǎo)航被觸發(fā)锻狗。
在失活的組件里調(diào)用離開守衛(wèi)满力。
調(diào)用全局的 beforeEach 守衛(wèi)。
在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)轻纪。
在路由配置里調(diào)用 beforeEnter油额。
解析異步路由組件。
在被激活的組件里調(diào)用 beforeRouteEnter刻帚。
調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)潦嘶。
導(dǎo)航被確認(rèn)。
調(diào)用全局的 afterEach 鉤子崇众。
觸發(fā) DOM 更新掂僵。
用創(chuàng)建好的實例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)。
vue-router hash 模式和 history 模式有什么區(qū)別顷歌?
區(qū)別:
url 展示上锰蓬,hash 模式有“#”,history 模式?jīng)]有
刷新頁面時眯漩,hash 模式可以正常加載到 hash 值對應(yīng)的頁面芹扭,而 history 沒有處理的話,會返回 404赦抖,一般需要后端將所有頁面都配置重定向到首頁路由舱卡。
兼容性。hash 可以支持低版本瀏覽器和 IE队萤。
vue-router hash 模式和 history 模式是如何實現(xiàn)的灼狰?
hash 模式:
#后面 hash 值的變化,不會導(dǎo)致瀏覽器向服務(wù)器發(fā)出請求浮禾,瀏覽器不發(fā)出請求交胚,就不會刷新頁面份汗。同時通過監(jiān)聽 hashchange 事件可以知道 hash 發(fā)生了哪些變化,然后根據(jù) hash 變化來實現(xiàn)更新頁面部分內(nèi)容的操作蝴簇。
history 模式:
history 模式的實現(xiàn)杯活,主要是 HTML5 標(biāo)準(zhǔn)發(fā)布的兩個 API,pushState 和 replaceState熬词,這兩個 API 可以在改變 url旁钧,但是不會發(fā)送請求。這樣就可以監(jiān)聽 url 變化來實現(xiàn)更新頁面部分內(nèi)容的操作互拾。
————————————————
版權(quán)聲明:本文為CSDN博主「普通網(wǎng)友」的原創(chuàng)文章歪今,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明颜矿。
原文鏈接:https://blog.csdn.net/weixin_46369542/article/details/104433260