vue生命周期面試題
vue 生命周期是什么?
Vue 實(shí)例從創(chuàng)建到銷毀的過(guò)程,就是生命周期
beforeCreate階段:vue實(shí)例的掛載元素el和數(shù)據(jù)對(duì)象data都是undefined,還沒(méi)有初始化。
created階段:vue實(shí)例的數(shù)據(jù)對(duì)象data有了,可以訪問(wèn)里面的數(shù)據(jù)和方法,未掛載到DOM,el還沒(méi)有
beforeMount階段:vue實(shí)例的el和data都初始化了,但是掛載之前為虛擬的dom節(jié)點(diǎn)
mounted階段:vue實(shí)例掛載到真實(shí)DOM上,就可以通過(guò)DOM獲取DOM節(jié)點(diǎn)
beforeUpdate階段:響應(yīng)式數(shù)據(jù)更新時(shí)調(diào)用,發(fā)生在虛擬DOM打補(bǔ)丁之前,適合在更新之前訪問(wèn)現(xiàn)有的DOM,比如手動(dòng)移除已添加的事件監(jiān)聽器
updated階段:虛擬DOM重新渲染和打補(bǔ)丁之后調(diào)用,組成新的DOM已經(jīng)更新,避免在這個(gè)鉤子函數(shù)中操作數(shù)據(jù),防止死循環(huán)
beforeDestroy階段:實(shí)例銷毀前調(diào)用,實(shí)例還可以用,this能獲取到實(shí)例,常用于銷毀定時(shí)器,解綁事件
destroyed階段:實(shí)例銷毀后調(diào)用,調(diào)用后所有事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例都會(huì)被銷毀
vue生命周期的作用是什么?
它的生命周期中有多個(gè)事件鉤子,讓我們?cè)诳刂普麄€(gè)Vue實(shí)例的過(guò)程時(shí)更容易形成好的邏輯
每個(gè)生命周期適合哪些場(chǎng)景?
生命周期鉤子的一些使用方法:
beforecreate : 可以在這加個(gè)loading事件,在加載實(shí)例時(shí)觸發(fā)
created : 初始化完成時(shí)的事件寫在這里,如在這結(jié)束loading事件,異步請(qǐng)求也適宜在這里調(diào)用
mounted : 掛載元素,獲取到DOM節(jié)點(diǎn)
updated : 如果對(duì)數(shù)據(jù)統(tǒng)一處理,在這里寫上相應(yīng)函數(shù)
beforeDestroy : 可以做一個(gè)確認(rèn)停止事件的確認(rèn)框
nextTick : 更新數(shù)據(jù)后立即操作dom
第一次頁(yè)面加載會(huì)觸發(fā)哪幾個(gè)鉤子?
第一次頁(yè)面加載時(shí)會(huì)觸發(fā) beforeCreate, created, beforeMount, mounted 這幾個(gè)鉤子
在beforeDestroy中我們都可以做那些事情
1.及時(shí)銷毀自定義事件,否則可能造成內(nèi)存泄露
2.解除綁定銷毀子組件以及事件監(jiān)聽器
何時(shí)需要使用beforeDestory?
1.解綁自定義事件event.$off
2.清除定時(shí)器
3.解綁自定義的dom事件,如window scroll 等
ajax請(qǐng)求應(yīng)該放在那個(gè)生命周期
mounted(整個(gè)渲染完成,dom加載完成)
js是單線程,ajax異步獲取數(shù)據(jù)
放在mounted 之前沒(méi)有用,只會(huì)讓邏輯更混亂
父子組件的生命周期觸發(fā)順序?
加載渲染過(guò)程:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子組件更新過(guò)程:
父beforeUpdate->子beforeUpdate->子updated->父updated
父組件更新過(guò)程:
父beforeUpdate->父updated
銷毀過(guò)程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
vue基本操作及原理面試題
v-show和v-if的區(qū)別?
v-show 是通過(guò)css 設(shè)置display控制顯示和隱藏
v-if是組件真正的渲染和銷毀,而不是顯示和隱藏
頻繁切換顯示狀態(tài)v-show,否則用v-if
Vue 中的 key 有什么作用?Vue 中 key 的作用是:key 是為 Vue 中 vnode 的唯一標(biāo)記,通過(guò)這個(gè) key,我們的 diff 操作可以更準(zhǔn)確、更快速 更準(zhǔn)確:因?yàn)閹?key 就不是就地復(fù)用了,在 sameNode 函數(shù) a.key === b.key 對(duì)比中可以避免就地復(fù)用的情況。所以會(huì)更加準(zhǔn)確。 更快速:利用 key 的唯一性生成 map 對(duì)象來(lái)獲取對(duì)應(yīng)節(jié)點(diǎn),比遍歷方式更快
ref的作用
1.獲取dom元素 this.$refs.box
2.獲取子組件中的 datathis.$refs.box.msg
調(diào)用子組件中的方法 this.$refs.box.open()
computed 和 watch 的區(qū)別和運(yùn)用的場(chǎng)景?
computed: 是計(jì)算屬性,依賴其它屬性值,并且 computed 的值有緩存,只有它依賴的屬性值發(fā)生改變,下一次獲取 computed 的值時(shí)才會(huì)重新計(jì)算 computed 的值;
watch: 更多的是「觀察」的作用,類似于某些數(shù)據(jù)的監(jiān)聽回調(diào) ,每當(dāng)監(jiān)聽的數(shù)據(jù)變化時(shí)都會(huì)執(zhí)行回調(diào)進(jìn)行后續(xù)操作;
運(yùn)用場(chǎng)景:
1.當(dāng)我們需要進(jìn)行數(shù)值計(jì)算,并且依賴于其它數(shù)據(jù)時(shí),應(yīng)該使用 computed,因?yàn)榭梢岳?computed 的緩存特性,避免每次獲取值時(shí),都要重新計(jì)算;
2.當(dāng)我們需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開銷較大的操作時(shí),應(yīng)該使用 watch,使用 watch 選項(xiàng)允許我們執(zhí)行異步操作 ( 訪問(wèn)一個(gè) API ),限制我們執(zhí)行該操作的頻率,并在我們得到最終結(jié)果前,設(shè)置中間狀態(tài)。這些都是計(jì)算屬性無(wú)法做到的。
如何將組件所有props傳遞給子組件?
<user v-bind = "$props"/>
復(fù)制代碼
多個(gè)組件有相同的邏輯,如何抽離?
mixin核心方法是 mergeOptions
可以幫助你合并數(shù)據(jù),合并方法,合并生命周期
雙向數(shù)據(jù)綁定的實(shí)現(xiàn)原理
1.vue 雙向數(shù)據(jù)綁定是通過(guò) 數(shù)據(jù)劫持 結(jié)合 發(fā)布訂閱模式的方式來(lái)實(shí)現(xiàn)的, 組件data的數(shù)據(jù)一旦變化,立刻觸發(fā)視圖的更新
2.核心 API - Object.defineProperty
Object.defineProperty缺點(diǎn):
1.深度監(jiān)聽,需要遞歸到底,一次性計(jì)算量大
2.無(wú)法監(jiān)聽新增屬性/刪除屬性(vue2.0可以使用vue.set vue.delete)
3.無(wú)法原生監(jiān)聽數(shù)組,需要特殊處理
Proxy 的優(yōu)勢(shì)
Proxy 可以直接監(jiān)聽對(duì)象而非屬性
Proxy 可以直接監(jiān)聽數(shù)組的變化
Proxy 有多達(dá) 13 種攔截方法,不限于apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具備的
Proxy 返回的是一個(gè)新對(duì)象,我們可以只操作新的對(duì)象達(dá)到目的,而 Object.defineProperty 只能遍歷對(duì)象屬性直接修改
Proxy 作為新標(biāo)準(zhǔn)將受到瀏覽器廠商重點(diǎn)持續(xù)的性能優(yōu)化,也就是傳說(shuō)中的新標(biāo)準(zhǔn)的性能紅利
為何組件data 必須是函數(shù)?
因?yàn)榻M件是可以復(fù)用的,JS 里對(duì)象是引用關(guān)系,如果組件 data 是一個(gè)對(duì)象,那么子組件中的 data 屬性值會(huì)互相污染,產(chǎn)生副作用。
所以一個(gè)組件的 data必須是一個(gè)函數(shù),因此每個(gè)實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝。
new Vue 的實(shí)例是不會(huì)被復(fù)用的,因此不存在以上問(wèn)題。
如何監(jiān)聽數(shù)組變化
1.重新定義原型
//重新定義數(shù)組的原型prototype
const oldArrayProperty=Array.prototype
//創(chuàng)建新對(duì)象,原型指向oldArrayProperty,再擴(kuò)展新的方法不會(huì)影響原型
const arrProto=Object.create(oldArrayProperty)
復(fù)制代碼
2.重寫push pop等方法
3.proxy可以原生支持監(jiān)聽數(shù)組變化
何時(shí)使用異步組件?
加載大組件 路由異步加載
vue 為何是異步渲染,$nextTick何用?
vue 是組件級(jí)更新 為了防止每次修改數(shù)據(jù)都更新視圖,所以使用異步渲染
異步渲染(以及合并data修改)提高渲染性能
$nextTick在DOM更新完之后,觸發(fā)回調(diào)
何時(shí)需要使用keep-alive?
緩存組件,不需要重復(fù)渲染
如多個(gè)靜態(tài)tab頁(yè)面切換,可以優(yōu)化性能
常用的2個(gè)屬性 include exclude
兩個(gè)生命周期 activated deactivated
LRU算法
vue 常見(jiàn)的性能優(yōu)化方式
合理使用v-show和v-if
合理使用computed 有緩存
v-for加key,以及避免和v-if同時(shí)使用
自定義事件,DOM 事件即時(shí)銷毀 (會(huì)導(dǎo)致內(nèi)存泄露)
合理使用異步組件
合理使用keep-alive
data層級(jí)不要太深,扁平化(深度監(jiān)聽時(shí)的一次性監(jiān)聽完成)
使用vue-loader 在開發(fā)環(huán)境做模板編譯(預(yù)編譯)
webpack 層級(jí)的優(yōu)化------
前端通用的性能優(yōu)化,如 圖片懶加載....
使用SSR
Vue 組件間通訊有哪幾種方式?
props/$emit適用 父子組件通信 這種方法是 Vue 組件的基礎(chǔ),相信大部分同學(xué)耳聞能詳,所以此處就不舉例展開介紹。ref與$parent/$children適用 父子組件通信
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實(shí)例
$parent/ $children :訪問(wèn)父 / 子實(shí)例
- EventBus (
$emit/$on) 適用于 父子、隔代、兄弟組件通信
這種方法通過(guò)一個(gè)空的 Vue 實(shí)例作為中央事件總線(事件中心),用它來(lái)觸發(fā)事件和監(jiān)聽事件,從而實(shí)現(xiàn)任何組件間的通信,包括父子、隔代、兄弟組件 4. $attrs / $listeners 適用于 隔代組件通信
$attrs :包含了父作用域中不被 prop 所識(shí)別 (且獲取) 的特性綁定 ( class 和 style 除外 )。當(dāng)一個(gè)組件沒(méi)有聲明任何 prop 時(shí),這里會(huì)包含所有父作用域的綁定 ( class 和 style 除外 ),并且可以通過(guò) v-bind=" $attrs " 傳入內(nèi)部組件。通常配合 inheritAttrs 選項(xiàng)一起使用。
$listeners :包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。它可以通過(guò) v-on=" $listeners" 傳入內(nèi)部組件
-
provide/inject適用于 隔代組件通信
祖先組件中通過(guò) provider 來(lái)提供變量,然后在子孫組件中通過(guò) inject 來(lái)注入變量。
provide / inject API 主要解決了跨級(jí)組件間的通信問(wèn)題,不過(guò)它的使用場(chǎng)景,主要是子組件獲取上級(jí)組件的狀態(tài),跨級(jí)組件間建立了一種主動(dòng)提供與依賴注入的關(guān)系。
6.Vuex 適用于 父子、隔代、兄弟組件通信
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。每一個(gè) Vuex 應(yīng)用的核心就是 store(倉(cāng)庫(kù))?!皊tore” 基本上就是一個(gè)容器,它包含著你的應(yīng)用中大部分的狀態(tài) ( state )。
Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新。
改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化。
vue3.0 有那些改進(jìn)?
vue3采用TS來(lái)編寫
支持 composition API 解決了mixin的問(wèn)題,讓代碼更有條理性
vue3 中的響應(yīng)式數(shù)據(jù)原理改成proxy
vdom的對(duì)比算法更新,只更新vdom的綁定來(lái)動(dòng)態(tài)數(shù)組部分
vuex 中action 和mutation 有何區(qū)別
mutaction 是同步更新數(shù)據(jù)(內(nèi)部會(huì)進(jìn)行是否為異步方式更新數(shù)據(jù)檢測(cè)) $watch 在嚴(yán)格模式下會(huì)報(bào)錯(cuò)
action 異步操作,可以獲取數(shù)據(jù)后調(diào)用mutaction 提交最終數(shù)據(jù)
vue-router 常見(jiàn)的路由模式?
hash 默認(rèn) h5 history (需要服務(wù)端支持)
實(shí)現(xiàn)的方式: hash onhashchange h5 history history.pushState
如何配置vue-router 異步加載?
在component 中配置 import
請(qǐng)用Vnode 描述一個(gè)DOM結(jié)構(gòu)
<div id="div1" calss="container">
<p>vdom</p>
<ul style="font-size:20px">
<li>a</li>
</ul>
</div>
//vnode
{
tag:'div',
props:{
className:'container',
id:'div1'
}
children:[
{
tag:'p',
children:'vdom'
},
{
tag:'ul',
props:{ style:'font-size :20px'},
children:[
{
tag:'li',
children:'a'
}
]
}
]
}
復(fù)制代碼
有想了解更多的小伙伴可以加Q群鏈接里面看一下,應(yīng)該對(duì)你們能夠有所幫助。