?39. Vue 中 key 的作用
vue 中 key 值的作用可以分為兩種情況來(lái)考慮:
第一種情況是 v-if 中使用 key。由于 Vue 會(huì)盡可能高效地渲染元 素,通常會(huì)復(fù)用已有元素而不是從頭開(kāi)始渲染。因此當(dāng)使用 v-if 來(lái) 實(shí)現(xiàn)元素切換的時(shí)候,如果切換前后含有相同類(lèi)型的元素,那么這個(gè) 元素就會(huì)被復(fù)用。如果是相同的 input 元素,那么切換前后用戶的 輸入不會(huì)被清除掉,這樣是不符合需求的。因此可以通過(guò)使用 key 來(lái) 唯一的標(biāo)識(shí)一個(gè)元素,這個(gè)情況下,使用 key 的元素不會(huì)被復(fù)用。這個(gè)時(shí)候 key 的作用是用來(lái)標(biāo)識(shí)一個(gè)獨(dú)立的元素。
第二種情況是 v-for 中使用 key。用 v-for 更新已渲染過(guò)的元素列 表時(shí),它默認(rèn)使用“就地復(fù)用”的策略。如果數(shù)據(jù)項(xiàng)的順序發(fā)生了改 變,Vue 不會(huì)移動(dòng) DOM 元素來(lái)匹配數(shù)據(jù)項(xiàng)的順序,而是簡(jiǎn)單復(fù)用此 處的每個(gè)元素。因此通過(guò)為每個(gè)列表項(xiàng)提供一個(gè) key 值,來(lái)以便 Vue 跟蹤元素的身份,從而高效的實(shí)現(xiàn)復(fù)用。這個(gè)時(shí)候 key 的作用是為 了高效的更新渲染虛擬 DOM。
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),比遍歷 方式更快
40.如何從真實(shí)DOM到虛擬DOM
涉及到Vue中的模板編譯原理,主要過(guò)程:
- 將模板轉(zhuǎn)換成?
ast
?樹(shù),?ast
?用對(duì)象來(lái)描述真實(shí)的JS語(yǔ)法(將真實(shí)DOM轉(zhuǎn)換成虛擬DOM) - 優(yōu)化樹(shù)
- 將?
ast
?樹(shù)生成代碼
41.為什么Vue采用異步渲染呢?
Vue 是組件級(jí)更新,如果不采用異步更新,那么每次更新數(shù)據(jù)都會(huì)對(duì)當(dāng)前組件進(jìn)行重新渲染,所以為了性能, Vue 會(huì)在本輪數(shù)據(jù)更新后,在異步更新視圖。核心思想 nextTick 。
dep.notify() 通知 watcher進(jìn)行更新, subs[i].update 依次調(diào)用 watcher 的 update , queueWatcher 將watcher 去重放入隊(duì)列, nextTick( flushSchedulerQueue )在下一tick中刷新watcher隊(duì)列(異步)。
42.為什么vue組件中data必須是一個(gè)函數(shù)?
對(duì)象為引用類(lèi)型,當(dāng)復(fù)用組件時(shí),由于數(shù)據(jù)對(duì)象都指向同一個(gè)data對(duì)象,當(dāng)在一個(gè)組件中修改data時(shí),其他重用的組件中的data會(huì)同時(shí)被修改;而使用返回對(duì)象的函數(shù),由于每次返回的都是一個(gè)新對(duì)象(Object的實(shí)例),引用地址不同,則不會(huì)出現(xiàn)這個(gè)問(wèn)題。
43.Vue-router 導(dǎo)航守衛(wèi)有哪些
- 全局前置/鉤子:beforeEach、beforeResolve、afterEach
- 路由獨(dú)享的守衛(wèi):beforeEnter
- 組件內(nèi)的守衛(wèi):beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
44.Vue 為什么要用 vm.$set() 解決對(duì)象新增屬性不能響應(yīng)的問(wèn)題 ?你能說(shuō)說(shuō)如下代碼的實(shí)現(xiàn)原理么?
1)Vue為什么要用vm.$set() 解決對(duì)象新增屬性不能響應(yīng)的問(wèn)題
- Vue使用了Object.defineProperty實(shí)現(xiàn)雙向數(shù)據(jù)綁定
- 在初始化實(shí)例時(shí)對(duì)屬性執(zhí)行 getter/setter 轉(zhuǎn)化
- 屬性必須在data對(duì)象上存在才能讓Vue將它轉(zhuǎn)換為響應(yīng)式的(這也就造成了Vue無(wú)法檢測(cè)到對(duì)象屬性的添加或刪除)
所以Vue提供了Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)
2)接下來(lái)我們看看框架本身是如何實(shí)現(xiàn)的呢?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-685422.html
Vue 源碼位置:vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any {
// target 為數(shù)組
if (Array.isArray(target) && isValidArrayIndex(key)) {
// 修改數(shù)組的長(zhǎng)度, 避免索引>數(shù)組長(zhǎng)度導(dǎo)致splcie()執(zhí)行有誤
target.length = Math.max(target.length, key)
// 利用數(shù)組的splice變異方法觸發(fā)響應(yīng)式
target.splice(key, 1, val)
return val
}
// key 已經(jīng)存在,直接修改屬性值
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
// target 本身就不是響應(yīng)式數(shù)據(jù), 直接賦值
if (!ob) {
target[key] = val
return val
}
// 對(duì)屬性進(jìn)行響應(yīng)式處理
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
我們閱讀以上源碼可知,vm.$set 的實(shí)現(xiàn)原理是:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-685422.html
- 如果目標(biāo)是數(shù)組,直接使用數(shù)組的 splice 方法觸發(fā)相應(yīng)式;
- 如果目標(biāo)是對(duì)象,會(huì)先判讀屬性是否存在、對(duì)象是否是響應(yīng)式,
- 最終如果要對(duì)屬性進(jìn)行響應(yīng)式處理,則是通過(guò)調(diào)用 defineReactive 方法進(jìn)行響應(yīng)式處理
defineReactive 方法就是 Vue 在初始化對(duì)象時(shí),給對(duì)象屬性采用 Object.defineProperty 動(dòng)態(tài)添加 getter 和 setter 的功能所調(diào)用的方法
到了這里,關(guān)于常見(jiàn)前端面試之VUE面試題匯總十三的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!