【直接收藏】前端 VUE 高階面試題(一)
說說vue動態(tài)權(quán)限綁定渲染列表(權(quán)限列表渲染)
首先請求服務(wù)器,獲取當(dāng)前用戶的權(quán)限數(shù)據(jù),比如請求 this.$http.get("rights/list");
獲取到權(quán)限數(shù)據(jù)之后,在列表中使用v-if v-if-else的組合來展示不同的內(nèi)容
Vue用的哪種設(shè)計模式
屬于發(fā)布訂閱模式,在vue中使用observer和definereactive兩個方法的結(jié)合對數(shù)據(jù)進行遞歸劫持,然后通過watch這個類來對屬性進行訂閱,Dep類用于解耦合,當(dāng)數(shù)據(jù)變更的時候先觸發(fā)數(shù)據(jù)的set方法,然后調(diào)用Dep.notiify通知視圖更新
說說vue操作真實dom性能瓶頸
vue性能瓶頸的幾種情況
一次渲染大量的數(shù)據(jù)的時候,存在大量數(shù)據(jù)并且都是復(fù)雜類型的時候,會導(dǎo)致vue對數(shù)據(jù)的劫持時間和渲染時間變長, js 連續(xù)執(zhí)行時間過長,會導(dǎo)致頁面長時間無法交互,而且渲染時間太慢,用戶一次交互反饋的時間過長。
優(yōu)化方案:可以使用
requestAnimation
這個方法,將數(shù)據(jù)進行分割,分批次渲染,減少了 js 的連續(xù)運行時間,并且加快了渲染時間,利用加長總運行時間換取了渲染時間,用戶既能快速得到反饋,而且不會因為過長時間的 js 運行而無法與頁面交互。當(dāng)頁面中存在大量數(shù)據(jù),只是修改了一小部分導(dǎo)致頁面也會導(dǎo)致頁面卡頓,因為vue的更新以組件為粒度進行更新的,只要修改了當(dāng)前組件中所使用的數(shù)據(jù),組件就會整個去進行更新,造成大量的時間浪費
優(yōu)化方案:將不同的模塊劃分成不同的組件,這樣有效降低虛擬dom的diff運算時間過長的問題,比如將大量數(shù)據(jù)的模塊單獨放一個組件,其它放一個組件,由于vue是以組件為粒度更新,修改其它組件的情況下不會導(dǎo)致table的重新diff,提升頁面響應(yīng)速度高達幾百倍
動態(tài)插槽作用域或者靜態(tài)插槽的更新
使用插槽作用域來替換這兩種操作方式,一樣能提升性能,因為使用
插槽作用域
之后,插槽內(nèi)容會被封裝到一個函數(shù)中,被子組件渲染,而不是在父組件
Vue中如何獲取dom、操作dom、更新dom
如何獲取dom?在Vue中提供了一種特別的方式來獲取dom,即給dom加上個ref屬性,那么就可以通過this.$refs.名字來獲取到該dom元素。
如何操作dom、更新dom?通過refs.名字就可以拿到對應(yīng)的真實dom,然后就可以用原生JS進行操作和更新。當(dāng)然vue框架本身就是不需要dom操作的,通過修改相應(yīng)的數(shù)據(jù)并再配合指令、模板語法就可以輕松的操作和更新dom。
Vue 的雙向數(shù)據(jù)綁定原理是什么
在Vue2.x中,雙向數(shù)據(jù)綁定是通過 數(shù)據(jù)劫持 結(jié)合 發(fā)布訂閱模式的方式來實現(xiàn)的,也就是說數(shù)據(jù)和視圖同步,數(shù)據(jù)發(fā)生變化,視圖跟著變化,視圖變化,數(shù)據(jù)也隨之發(fā)生改變。核心:關(guān)于VUE雙向數(shù)據(jù)綁定,其核心是 Object.defineProperty()方法。
Vue3.x則是用ES6的語法Proxy對象來實現(xiàn)的。
Object.defineProperty()的缺點:
只能監(jiān)聽對象(Object),不能監(jiān)聽數(shù)組的變化,無法觸發(fā)push, pop, shift, unshift,splice, sort, reverse。
必須遍歷對象的每個屬性
只能劫持當(dāng)前對象屬性,如果想深度劫持,必須深層遍歷嵌套的對象。
?Proxy的優(yōu)點:
Proxy 可以直接監(jiān)聽對象而非屬性。
Proxy 可以直接監(jiān)聽數(shù)組的變化。
Proxy 有多達 13 種攔截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具備的。
Proxy 返回的是一個新對象,我們可以只操作新的對象達到目的,而 Object.defineProperty 只能遍歷對象屬性直接修改。
Proxy 作為新標準將受到瀏覽器廠商重點持續(xù)的性能優(yōu)化,也就是傳說中的新標準的性能紅利。
mvvm框架是什么
MVVM是Model-View-ViewModel的簡寫。它本質(zhì)上就是MVC(Model-View-Controller)的改進版。在開發(fā)過程中,由于需求的變更或添加,項目的復(fù)雜度越來越高,代碼量越來越大,此時我們會發(fā)現(xiàn)MVC維護起來有些吃力,尤其Controller控制層非常的厚重,非常的龐大,難以維護。
所以有人想到把Controller的數(shù)據(jù)和邏輯處理部分從中抽離出來,用一個專門的對象去管理,這個對象就是ViewModel。ViewModel 是由前端開發(fā)人員組織生成和維護的視圖數(shù)據(jù)層。在這一層,前端開發(fā)者對從后端獲取的 Model 數(shù)據(jù)進行轉(zhuǎn)換處理,做二次封裝,以生成符合 View 層使用預(yù)期的視圖數(shù)據(jù)模型。
由于實現(xiàn)了雙向綁定,ViewModel 的內(nèi)容會實時展現(xiàn)在 View 層,這是激動人心的,因為前端開發(fā)者再也不必低效又麻煩地通過操縱 DOM 去更新視圖,MVVM 框架已經(jīng)把最臟最累的一塊做好了,我們開發(fā)者只需要處理和維護 ViewModel,更新數(shù)據(jù)視圖就會自動得到相應(yīng)更新,真正實現(xiàn)數(shù)據(jù)驅(qū)動開發(fā)。

談?wù)刅ue的token存儲
在前后端完全分離的情況下,Vue項目中實現(xiàn)token驗證大致思路如下:
1、第一次登錄的時候,前端調(diào)后端的登陸接口,發(fā)送用戶名和密碼
2、后端收到請求,驗證用戶名和密碼,驗證成功,就給前端返回一個token
3、前端拿到token,將token存儲到localStorage和vuex中,并跳轉(zhuǎn)路由頁面
4、前端每次跳轉(zhuǎn)路由,就判斷 localStroage 中有無 token ,沒有就跳轉(zhuǎn)到登錄頁面,有則跳轉(zhuǎn)到對應(yīng)路由頁面
5、每次調(diào)后端接口,都要在請求頭中加token
6、后端判斷請求頭中有無token,有token,就拿到token并驗證token,驗證成功就返回數(shù)據(jù),驗證失?。ɡ纾簍oken過期)就返回401,請求頭中沒有token也返回401
7、如果前端拿到狀態(tài)碼為401,就清除token信息并跳轉(zhuǎn)到登錄頁面
知道nextTick的作用嗎,談?wù)剬λ睦斫?,是什么,怎么?/span>
當(dāng)你設(shè)置 vm.message = 'new message',該組件不會立即重新渲染。當(dāng)刷新隊列時,組件會在下一個事件循環(huán)“tick”中更新。多數(shù)情況我們不需要關(guān)心這個過程,但是如果你想基于更新后的 DOM 狀態(tài)來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發(fā)人員使用“數(shù)據(jù)驅(qū)動”的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback)。這樣回調(diào)函數(shù)將在 DOM 更新完成后被調(diào)用。例如:
nextTick和setTimeout區(qū)別
?首先Vue 在更新 DOM 時是異步執(zhí)行的,也就是說數(shù)據(jù)變了,DOM不會立即改變,那么我們是如何知道DOM什么時候會改變呢?也就是說如何知道異步后的觸發(fā)時機呢?
?可以通過nextTick方法,這個方法在源碼內(nèi),先監(jiān)聽是否具備Promise.then,利用promise來監(jiān)聽,如果當(dāng)前環(huán)境不支持promise,那么就降級采用MutationObserver,如果MutationObserver不支持的話,那么就降級采用setImmediate,如果setImmediate不支持的話,那么就使用setTimeout(fn, 0)。
?所以說nextTick和setTimeout區(qū)別總結(jié)就是:nextTick會先嘗試使用promise、MutationObserver、setImmediate這些技術(shù)去監(jiān)聽,如果都不支持才會采用setTimeout
vue中為什么用虛擬dom而不操作真實dom
起初我們在使用JS/JQuery時,不可避免的會大量操作DOM,而DOM的變化又會引發(fā)回流或重繪,從而降低頁面渲染性能。那么怎樣來減少對DOM的操作呢?此時虛擬DOM應(yīng)用而生,所以虛擬DOM出現(xiàn)的主要目的就是為了減少頻繁操作DOM而引起回流重繪所引發(fā)的性能問題的!
虛擬DOM(Virtual Dom),起始本質(zhì)上就是一個JS對象,當(dāng)數(shù)據(jù)發(fā)生變化時,我們不直接操作真實DOM,因為很昂貴,我們?nèi)ゲ僮鬟@個JS對象,就不會觸發(fā)大量回流重繪操作,再加上diff算法,可以找到兩次虛擬DOM之間改變的部分,從而最小量的去一次性更新真實DOM,而不是頻繁操作DOM,性能得到了大大的提升。

Vue如何進行組件傳值
父向子組件傳值,可以利用prop方式。
子向父組件傳值,可以利用自定義事件$emit方式。

多層級組件傳值,可以使用provide/inject

無關(guān)系的組件傳值,利用vuex狀態(tài)管理

說說vue里面的父子通信
父 -> 子: 通過 Prop 向子組件傳遞數(shù)據(jù),子組件通過props屬性來接收。
子 -> 父: 父組件自定義事件,子組件利用$emit來完成。

談?wù)勅绾螌崿F(xiàn)vue組件通信和傳值方式 (兩個問題為同一個答案問法不一樣)
這類問題 首先分類 表明了解的比較多 ? 具體就沒說完 或者漏了 ?面試官也不會計較很多
組件通信的四大類 ? 父與子 ? ?子與父 ? ?子與子 ? ? 跨層級 ?
在細說各種方式 加入自己的理解
1、props和$emit
父組件向子組件傳遞數(shù)據(jù)是通過prop傳遞的,子組件傳遞數(shù)據(jù)給父組件是通過$emit觸發(fā)事件
2、$attrs和$listeners
3、中央事件總線 bus
上面兩種方式處理的都是父子組件之間的數(shù)據(jù)傳遞,而如果兩個組件不是父子關(guān)系呢?這種情況下可以使用中央事件總線的方式。新建一個Vue事件bus對象,然后通過bus.$emit觸發(fā)事件,bus.$on監(jiān)聽觸發(fā)的事件。
4、provide和inject
父組件中通過provider來提供變量,然后在子組件中通過inject來注入變量。不論子組件有多深,只要調(diào)用了inject那么就可以注入provider中的數(shù)據(jù)。而不是局限于只能從當(dāng)前父組件的prop屬性來獲取數(shù)據(jù),只要在父組件的生命周期內(nèi),子組件都可以調(diào)用。
5、v-model
父組件通過v-model傳遞值給子組件時,會自動傳遞一個value的prop屬性,在子組件中通過this.$emit(‘input’,val)自動修改v-model綁定的值
6、$parent和$children
7、boradcast和dispatch
8、vuex處理組件之間的數(shù)據(jù)交互 如果業(yè)務(wù)邏輯復(fù)雜,很多組件之間需要同時處理一些公共的數(shù)據(jù),這個時候才有上面這一些方法可能不利于項目的維護,vuex的做法就是將這一些公共的數(shù)據(jù)抽離出來,然后其他組件就可以對這個公共數(shù)據(jù)進行讀寫操作,這樣達到了解耦的目的。
說說vue中Key值的作用
關(guān)于這個可以的key的作用 首先表明 key 不是一定要有的 ?不寫可以代碼也可以跑 ?但是建議加上
? ? 然后指出可以用的地方 ?key在v-for循環(huán)可以用用 ? 在表單元素中也可以用key 減少緩存
? ? 一般說key ?只要說配合v-for的使用
? ?
key是為Vue中的vnode標記的唯一id,通過這個key,我們的diff操作可以更準確、更快速
diff算法的過程中,先會進行新舊節(jié)點的首尾交叉對比,當(dāng)無法匹配的時候會用新節(jié)點的key與舊節(jié)點進行比對,然后超出差異能講清楚diff算法就繼續(xù)講
diff程可以概括為:oldCh和newCh各有兩個頭尾的變量StartIdx和EndIdx,它們的2個變量相互比較,一共有4種比較方式。如果4種比較都沒匹配,如果設(shè)置了key,就會用key進行比較,在比較的過程中,變量會往中間靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一個已經(jīng)遍歷完了,就會結(jié)束比較,這四種比較方式就是首、尾、舊尾新頭、舊頭新尾.
準確: 如果不加key,那么vue會選擇復(fù)用節(jié)點(Vue的就地更新策略),導(dǎo)致之前節(jié)點的狀態(tài)被保留下來,會產(chǎn)生一系列的bug. 快速: key的唯一性可以被Map數(shù)據(jù)結(jié)構(gòu)充分利用,相比于遍歷查找的時間復(fù)雜度O(n),Map的時間復(fù)雜度僅僅為O(1)
講完以后 還要補充一點自己的看法
建議使用主鍵比如id ?
? ?
? ?
說說vue中的虛擬dom和diff算法
Virtual DOM 其實就是一棵以 JavaScript 對象( VNode 節(jié)點)作為基礎(chǔ)的樹,用對象屬性來描述節(jié)點,實際上它只是一層對真實 DOM 的抽象。最終可以通過一系列操作使這棵樹映射到真實的DOM上
下面就是一個真實DOM映射到虛擬DOM的例子:
<ul id='list'>
? ? ? ? ?<li>Item 1</li>
? ? ? ? ?<li>Item 2</li>
? ? ? ? ?<li>Item 3</li>
? ? ? ?</ul>
? ? ? ?
var element = {
? ? ? ?tagName: 'ul', // 節(jié)點標簽名
? ? ? ?props: { // DOM的屬性,用一個對象存儲鍵值對
? ? ? ? ? ?id: 'list'
? ? ? ?},
? ? ? ?children: [ // 該節(jié)點的子節(jié)點
? ? ? ? ?{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
? ? ? ? ?{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
? ? ? ? ?{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
? ? ? ?]
? ?}
? ?
?在補充點虛擬DOM的好處
具備跨平臺的優(yōu)勢
由于 Virtual DOM 是以 JavaScript 對象為基礎(chǔ)而不依賴真實平臺環(huán)境,所以使它具有了跨平臺的能力,比如說瀏覽器平臺、Weex、Node 等。
操作原生DOM慢,js運行效率高。我們可以將DOM對比操作放在JS層,提高效率。
因為DOM操作的執(zhí)行速度遠不如Javascript的運算速度快,因此,把大量的DOM操作搬運到Javascript中,運用patching算法來計算出真正需要更新的節(jié)點,最大限度地減少DOM操作,從而顯著提高性能。
Virtual DOM 本質(zhì)上就是在 JS 和 DOM 之間做了一個緩存??梢灶惐?CPU 和硬盤,既然硬盤這么慢,我們就在它們之間加個緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個緩存。CPU(JS)只操作內(nèi)存(Virtual DOM),最后的時候再把變更寫入硬盤(DOM)
提升渲染性能
Virtual DOM的優(yōu)勢不在于單次的操作,而是在大量、頻繁的數(shù)據(jù)更新下,能夠?qū)σ晥D進行合理、高效的更新。
diff算法
vdom因為是純粹的JS對象,所以操作它會很高效,但是vdom的變更最終會轉(zhuǎn)換成DOM操作,為了實現(xiàn)高效的DOM操作,一套高效的虛擬DOM diff算法顯得很有必要
diff算法包括一下幾個步驟:
用 JavaScript 對象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個樹構(gòu)建一個真正的 DOM 樹,插到文
檔當(dāng)中
當(dāng)狀態(tài)變更的時候,重新構(gòu)造一棵新的對象樹。然后用新的樹和舊的樹進行比較(diff),記錄兩棵樹差異
把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上(patch),視圖就更新了
diff算法是通過同層的樹節(jié)點進行比較而非對樹進行逐層搜索遍歷的方式,所以時間復(fù)雜度只有O(n),是一種相當(dāng)高效的算法
vue3.0有了解過嗎,你覺得vue3.0好嗎,好在哪
這種問題 是開放的 ? 多說就是都是對的 ? ?可以講差異 ?也可以講新增 的知識點 ?
比如說 常用的api特別好用
ref、toRefs、toRef、isRef
ref 用于定義響應(yīng)式變量、快捷DOM訪問。
基本語法:
const a = ref(1) // {value:1}
基礎(chǔ)使用: 一般用于定義 String、Number、Boolean 這種基于數(shù)據(jù)類型,外在表現(xiàn)統(tǒng)一使用 .value 訪問。
補充:ref 還可以訪問 DOM對象或者組件實例對象,可做DOM操作。
toRef、toRefs 用于把一個object的變量,變成響應(yīng)式的變量。
基本語法:
const msg = toRef(obj, key)
// 把obj[key]變成響應(yīng)式的基本語法:
const { msg } = toRefs(obj)
// 把整個obj都變成響應(yīng)式的unref 返回一個變量的值
基本語法:
const x = unref(x)
// 如果x是ref變量則返回x.value,如果x不是ref變量則直接返回x。isRef 用于判斷一個變量是不是ref響應(yīng)式變量
基本語法:
const bol = isRef(x)
shallowRef、triggerRef
shallowRef 用于性能優(yōu)化,只對對象的第一層進行proxy
基本語法:
const obj = shallowRef({a:1,b:{c:{d:{e:2}}}})
triggerRef 用于手動觸發(fā)那些shallowRef的變量進行更新視圖
基本語法:
triggerRef(obj)
customRef 自定義ref,把ref變量拆成get/set的寫法
基本語法:
customRef((track, trigger) =>({get,set})
reactive、readonly
基本語法:
const arr = reactive([]) // {value: []}
ref和reactive是什么關(guān)系呢?ref背后是使用reactive來實現(xiàn)的。
shallowReactive 用于性能優(yōu)化,只對對象的第一層進行proxy
基本語法:
const c = shallowReactive({a:{b:{c:100}}})
// 只對這個對象的第一層進行proxyreadonly 把響應(yīng)式變量變成“只讀的”,如果修改就報警告。
基本語法:
const user = readonly({name:1,age:2})
isReadonly 用于判斷一個變量是否是readonly的,返回布爾值
基本語法:
const bol = isReadonly(x)
isProxy 用于判斷一個變量是否是響應(yīng)式的,返回布爾值
基本語法:
const bol = isProxy(x)
isReactive 用于判斷一個變量是否是reactive響應(yīng)式變量,返回布爾值
基本語法:
const bol = isReactive(x)
toRaw、markRaw
toRaw 用于返回一個響應(yīng)式變量的原始值
基本語法:
const a3 = toRow(reactive(a1))
// a1===a3是truemarkRaw 用于把一個普通變量標記成“不可proxy”的
基本語法:
const b2 = markRaw(b1)
computed、watch、watchEffect
computed 用于對響應(yīng)式變量進行二次計算,當(dāng)它依賴的響應(yīng)式變量發(fā)生變化時會重新計算
基本語法:
const c = computed(()=>c1.value*c2.value)
// 只讀基本語法: // 可寫可讀
watch 用于監(jiān)聽響應(yīng)式變量的變化,組件初始化它不執(zhí)行
基本語法:
const stop = watch(x, (new,old)=>{})
// 調(diào)用stop()可以停止監(jiān)聽基本語法:
const stop = watch([x,y], ([newX,newY],[oldX,oldY])=>{})
watchEffect 用于監(jiān)聽響應(yīng)式變量的變化,組件初始化會執(zhí)行
基本語法:
const stop = watchEffect(()=>ajax({cate,page,size}))
2:也可以說亮點
性能比vue2.x快1.2~2倍
支持tree-shaking,按需編譯,體積比vue2.x更小
支持組合API
更好的支持TS
更先進的組
3.更可以說性能
1.diff算法更快
vue2.0是需要全局去比較每個節(jié)點的,若發(fā)現(xiàn)有節(jié)點發(fā)生變化后,就去更新該節(jié)點
vue3.0是在創(chuàng)建虛擬dom中,會根據(jù)DOM的的內(nèi)容會不會發(fā)生內(nèi)容變化,添加靜態(tài)標記, 誰有flag!比較誰。
2、靜態(tài)提升
vue2中無論元素是否參與更新,每次都會重新創(chuàng)建,然后再渲染 vue3中對于不參與更新的元素,會做靜態(tài)提升,只被創(chuàng)建一次,在渲染時直接復(fù)用即可
3、事件偵聽緩存
默認情況下,onclick為動態(tài)綁定,所以每次都會追蹤它的變化,但是因為是同一函數(shù),沒有必要追蹤變化,直接緩存復(fù)用即可
在之前會添加靜態(tài)標記8 會把點擊事件當(dāng)做動態(tài)屬性 會進行diff算法比較, 但是在事件監(jiān)聽緩存之后就沒有靜態(tài)標記了,就會進行緩存復(fù)用
v-model有了解過嗎,原理是什么
這種原理性問題 ?不要直接說不清楚 不了解 ?
先講下使用
v-model本質(zhì)上是一個語法糖,可以看成是value + input 方法的語法糖。可以通過model的prop屬性和event事件來進行自定義。
2、v-model是vue的雙向綁定的指令,能將頁面上控件輸入的值同步更新到相關(guān)綁定的data屬性, 也會在更新data
綁定屬性時候,更新頁面上輸入控件的值。
然后再來講細節(jié)
vue的雙向綁定是由數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式實現(xiàn)的,那么什么是數(shù)據(jù)劫持?vue是如何進行數(shù)據(jù)劫持的?說白了就是通過Object.defineProperty()來劫持對象屬性的setter和getter操作,在數(shù)據(jù)變動時做你想要做的事情
我們已經(jīng)知道實現(xiàn)數(shù)據(jù)的雙向綁定,首先要對數(shù)據(jù)進行劫持監(jiān)聽,所以我們需要設(shè)置一個監(jiān)聽器Observer,用來監(jiān)聽所有屬性。如果屬性發(fā)生變化了,就需要告訴訂閱者Watcher看是否需要更新。因為訂閱者是有很多個,所以我們需要有一個消息訂閱器Dep來專門收集這些訂閱者,然后在監(jiān)聽器Observer和訂閱者Watcher之間進行統(tǒng)一管理的。接著,我們還需要有一個指令解析器Compile,對每個節(jié)點元素進行掃描和解析,將相關(guān)指令(如v-model,v-on)對應(yīng)初始化成一個訂閱者Watcher,并替換模板數(shù)據(jù)或者綁定相應(yīng)的函數(shù),此時當(dāng)訂閱者Watcher接收到相應(yīng)屬性的變化,就會執(zhí)行對應(yīng)的更新函數(shù),從而更新視圖。因此接下去我們執(zhí)行以下3個步驟,實現(xiàn)數(shù)據(jù)的雙向綁定:
1.實現(xiàn)一個監(jiān)聽器Observer,用來劫持并監(jiān)聽所有屬性,如果有變動的,就通知訂閱者。
2.實現(xiàn)一個訂閱者Watcher,每一個Watcher都綁定一個更新函數(shù),watcher可以收到屬性的變化通知并執(zhí)行相應(yīng)的函數(shù),從而更新視圖。
3.實現(xiàn)一個解析器Compile,可以掃描和解析每個節(jié)點的相關(guān)指令(v-model,v-on等指令),如果節(jié)點存在v-model,v-on等指令,則解析器Compile初始化這類節(jié)點的模板數(shù)據(jù),使之可以顯示在視圖上,然后初始化相應(yīng)的訂閱者(Watcher)
3:最后補一下 vue2.0里面用Object.defineProperty ?3.0里面用new ?Proxy ? ? 一個監(jiān)聽每個屬性 一個監(jiān)聽整個對象
VUE組件如何與iframe通信問題
像這種問題其實問的不是特別詳情 ?面試者可能不懂題目的意思 ? 但是我們要學(xué)會揣摩 面試官的問題
如果不知道 你就直說vue的組件通信 在講iframe的頁面獲取v
vue組件內(nèi)嵌一個iframe,現(xiàn)在想要在iframe內(nèi)獲取父組件內(nèi)信息,采用的是H5新特性PostMessage來解決跨域問題
采用postMessage內(nèi)涵兩個API:
onMessage:消息監(jiān)聽
postMessage:消息發(fā)送
代碼和例子
用過VUE 的自定義指令嗎?自定義指令的方法有哪些
這種問題一樣的 ?先回答經(jīng)常用的一些指定 比如 v-for ?v-if ?v-model ? v-show等等之類的 ?指令分為全局和局部的
當(dāng)修改data時Vue的組件重渲染是異步還是同步
這個問題很有意思 ?因為平時我們一般問題異步和同步指的是 數(shù)據(jù)請求 同步和異步問題
這里加上了組件 ?還有修改data ? ? 這里給大家寫個例子
以此可以說明 ?
數(shù)據(jù)更新是同步的 ?但是視圖更新是異步的
.sync修飾器的作用是
首先看到 .sync ?我們需要知道這是個修飾器 ? 類似修飾器還有 ?.stop ?.prevent ?之類
其實這個修飾符就是vue封裝了 子組件要修改父組件傳過來的動態(tài)值的語法糖,省去了父組件需要寫的方法,但是子組件emit時要加上update
在有些情況下,我們可能需要對一個 prop 進行“雙向綁定”。不幸的是,真正的雙向綁定會帶來維護上的問題,因為子組件可以修改父組件,且在父組件和子組件都沒有明顯的改動來源
代碼解釋
這里關(guān)鍵就是emit里的參數(shù)要寫成'update'+ ':' +'要修改的props'
這個問題其實也是屬于組件通信 ? 常見的組件通信有 父傳子 ?子傳父 ?子傳子 ?以及跨層級
這個多組件嵌套通信其實就是跨層級的另一種問法
多組件通信
方法一:props ?一層 一層的傳遞
方法二:依賴注入 ?provide 聲明 ?inject接收
方法三:利用公共的bus = new ?Vue() ? bus.$on ?聲明 ?bus.$emit() ? 調(diào)用
方法四:使用vuex 全局的狀態(tài)管理
vue如何讓css只在當(dāng)前組件生效
當(dāng)前組件<style>寫成<style ?scoped> ? 加上scoped就可以了
這個style中一般還有l(wèi)ang ? lang可以是less ?scss ?stylus 等等
不加scoped就是全局的樣式
Vue 的 keep-live 用過嗎?作用是什么?
沒有用過
用過,它的作用是可以在組件切換時,保存其包裹的組件的狀態(tài),使其不被銷毀,防止多次渲染。
keepalive,添加這個會比平常多生命周期嗎? keepalive 已經(jīng)緩存了,但是想跳回去的時候添加新的屬性在哪個生命周期里實現(xiàn)
?會比平常的組件多兩個生命周期鉤子函數(shù),分別是:activated 和 deactivated。使用keep-alive
包裹的組件在切換時不會被銷毀,而是緩存到內(nèi)存中并執(zhí)行 deactivated 鉤子函數(shù),再次渲染后會執(zhí)行 activated 鉤子函數(shù)。如果再一次跳回顯示組件的時候可以在 activated 中做處理
說一下 keep-alive 的關(guān)聯(lián)生命周期
?會比平常的組件多兩個生命周期鉤子函數(shù),分別是:activated 和 deactivated。使用keep-alive
包裹的組件在切換時不會被銷毀,而是緩存到內(nèi)存中并執(zhí)行 deactivated 鉤子函數(shù),再次渲染后會執(zhí)行 activated 鉤子函數(shù)。
Vue 創(chuàng)建項目的指令是什么
使用的官方 cli 腳手架,如果是低于 3.0 的版本,使用
npm init
cli 的版本大于 3.0 的使用
vue create
可以使用 vite 直接搭建項目,命令為
npm init vite@latest
,根據(jù)提示,一步一步操作就好
vue 中如何使用 ref 綁定
?通過為組件或者標簽添加 ref 屬性,可以在 js 代碼中使用全局 api$refs
獲取 dom 元素或者組件,其上的方法或者屬性可以直接進行操作。
vue 導(dǎo)航守衛(wèi)與 jq 導(dǎo)航攔截器的介紹
?vue 的導(dǎo)航守衛(wèi)一般指的是路由導(dǎo)航守衛(wèi),作用是在頁面跳轉(zhuǎn)的時候可以執(zhí)行一個鉤子函數(shù)。
?導(dǎo)航守衛(wèi)使用最多的是全局守衛(wèi) router.beforeEach 主要是用來驗證用戶的登陸狀態(tài)。它接收三個參數(shù) to, from, next
to: 即將要進入的路由對象
from: 當(dāng)前導(dǎo)航要離開的路由
next: 一個回調(diào)函數(shù), 一定要調(diào)用這個方法,不然路由不會繼續(xù)往下
jq 導(dǎo)航攔截器沒有聽過,一般在 jQuery 的作用就是對 dom 元素做操作,jQuery 的核心功能是元素選擇器。至于提到的導(dǎo)航器可能是一類第三方 jQuery 插件?或者網(wǎng)絡(luò)請求攔截,如果是網(wǎng)絡(luò)請求攔截,那么 jQuery 發(fā)起請求的話,可以封裝一個全局 ajax 請求插件,通過設(shè)置 ajaxSetup 實現(xiàn)
?// 參考這個 https://www.runoob.com/jquery/ajax-ajaxsetup.html
?$.ajaxSetup({
? ?// url: 'demo_ajax_load.txt',
? ?beforeSend() {
? ? ?// 發(fā)起請求之前執(zhí)行
? ?},
? ?complete() {
? ? ?// 所有的請求成功之后執(zhí)行
? ?},
?});
vue 常用哪些命令
v-model 指令,用于表單輸入。
v-on 指令,用于事件綁定。
v-bind 指令,用于動態(tài)綁定一個值和傳入變量。
v-once 指令,事件只能用一次,無論點擊幾次,執(zhí)行一次之后都不會再執(zhí)行。
v-html 指令,會將 span 的內(nèi)容替換成 rawHtml 的屬性值,直接作為 HTML 代碼解析。
v-for 指令,與 HTML 標簽結(jié)合使用,用于數(shù)據(jù)的遍歷擺放。
v-if 指令,用來進行條件判斷的,直接操作 dom。
v-else 指令,用來進行條件判斷的,與 v-if 指令連用,意義為條件不成立時執(zhí)行。
v-show 指令,根據(jù)真假切換元素的顯示狀態(tài)。
vue 中插槽共有幾種,及插槽的作用
?三種:默認插槽、具名插槽、作用域插槽
默認插槽
默認插槽就是指<slot>,<slot>的作用類似于占符。
具名插槽
可以通過設(shè)置 name 屬性,指定顯示的位置
定義一個<base-layout>
vue 如何使用插件
?直接安裝,引入就能使用。vue 還是 js,只要是 js 那么所有的插件使用都是相同的方式,引入綁定到對應(yīng)的節(jié)點或者操作對應(yīng)的節(jié)點就好。
Vue 組件懶加載,圖片懶加載
組件懶加載
結(jié)合路由插件使用的時候使用 import 方式實現(xiàn)
就是在加載頁面的時候,如果頁面中的圖片過多,可以使用占位符的方式替換沒有在可是區(qū)域內(nèi)的圖片,只加載當(dāng)前需要現(xiàn)實的圖片。監(jiān)聽滾動條的位置,當(dāng)圖片標簽出現(xiàn)在可視區(qū)域的時候,重置圖片的路徑為真是路徑,然后展示圖片地址。一般在實際開發(fā)的時候都直接使用圖片懶加載插件實現(xiàn)。還有一種解決方案就是使用頁面骨架屏效果,也是類似占位顯示,當(dāng)數(shù)據(jù)加載完成之后替換掉占位顯示的內(nèi)容
使用Vue封裝過組件嗎?有哪些?講一下他們是怎么實現(xiàn)的
比如做后臺管理中,很多模塊經(jīng)常會復(fù)用,比如側(cè)邊導(dǎo)航組件、項目中常用的 echarts圖表的封裝(比如折線圖、柱狀圖等)
封裝組件需要考慮復(fù)用性:
預(yù)留插槽slot, 多次調(diào)用如果 子組件視圖結(jié)構(gòu)不一樣那么就要 在 子組件template預(yù)留好 插槽(單個插槽、具名插槽,作用域插槽)
考慮到數(shù)據(jù)傳遞,定義props 組件接收父組件傳遞的數(shù)據(jù),同時需要注意單向數(shù)據(jù)流,props不能直接修改,$emit自定義事件,父組件修改
業(yè)務(wù)邏輯不要在子組件中處理,子組件在不同父組件中調(diào)用時,業(yè)務(wù)處理代碼不同,切記不要直接在子組件中處理業(yè)務(wù),應(yīng)該子組件 $emit自定義事件,將數(shù)據(jù)傳遞給父組件,父組件處理業(yè)務(wù)。
說說vuex的管理操作或理解
vuex是 vue的一個狀態(tài)管理插件,采用集中式管理方式,來管理項目中多個組件的公共狀態(tài)。
vuex有一個倉庫概念,將組件公共的state存儲在倉庫的state屬性中,state是只讀的,組件只能使用,不能直接修改,修改需要通過 倉庫中的mutations模塊來修改,這樣的好處是 當(dāng)數(shù)據(jù)修改便于溯源,且不會因為 多個組件 直接修改數(shù)據(jù),導(dǎo)致 組件間數(shù)據(jù)的互相影響, 同時 當(dāng)我們倉庫中有一個state 數(shù)據(jù)需要請求 數(shù)據(jù)接口才能獲取時,vuex 設(shè)計了一個action模塊,在action模塊中發(fā)送異步請求,得到數(shù)據(jù)后,提交mutation來修改state。當(dāng)state發(fā)生改變后組件自動刷新,在組件中可以commit mutation或者dispatch action來修改state。
具體工作流程如下圖

說說Vuex的工作流程
vuex的倉庫有5個模塊,分別是 state,mutations, actions, getters, modules
我們將組件的公共狀態(tài)定義在 vuex倉庫的state中,state是只讀的,無法直接修改,必須調(diào)動倉庫中的某個mutation才能修改狀態(tài),getters可以理解為vuex中的計算屬性,當(dāng)我們在某個組件中使用vuex中的某個state時,不是直接使用原值,而是需要派生出一個新的值,就可以定義getters,可以在組件中獲取。當(dāng)依賴的state發(fā)生改變,此時getters會重新計算得到新值,同時 action中可以發(fā)送異步請求,得到數(shù)據(jù)后,commit mutation來給state賦值
具體代碼如下:
倉庫代碼
組件中使用 使用vuex
vuex項目中怎么使用?工作原理是什么?
原則:
中小型項目中,如果組件的公共狀態(tài)不多的情況下,不建議使用vuex,反而會增加代碼復(fù)雜度,想要組件通信,直接通過event bus即可,中大型項目中,多個組件公共狀態(tài)較多情況下,建議使用vuex
vuex的具體工作流程如下:
在倉庫state中定義公共狀態(tài),action中發(fā)送異步請求,得到數(shù)據(jù)后調(diào)用mutation 賦值給state,組件中使用state,也可以在組件中 dispatch action和觸發(fā)mutation來修改state,視圖刷新
具體代碼如下:
倉庫代碼
組件中使用 使用vuex
Vuex中處理異步需要在什么地方寫
異步處理需要在 倉庫的actions中定義
Action 類似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作。
我們可以在action中發(fā)送異步請求,成功后觸發(fā)mutation 將結(jié)果傳入,在mutation賦值給state
請你談?wù)勀銓uex的理解
vuex是專為vue設(shè)計的狀態(tài)管理工具,可用于父子組件和非父子組件的全局組件通信。應(yīng)用的狀態(tài)集中放在store中,改變狀態(tài)必須要經(jīng)過commit,同步改變狀態(tài)是提交mutations,異步是先通過actions再通過mutations。
一共有5大模塊
- state存放狀態(tài)
- getters就像計算屬性一樣,getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會被重新計算。可以對state中的數(shù)據(jù)做一些處理
- mutations更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation,通過store.commit提交到mutations模塊
- actionsactions是異步的改變state中狀態(tài)的方法,通過store.dispatch來提交到mutations模塊,再通過提交commit來更改state中的狀態(tài)
- modulesVuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割
vuex—個模塊中改變state中數(shù)據(jù),其他模塊如何獲取
由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會集中到一個比較大的對象。當(dāng)應(yīng)用變得非常復(fù)雜時,store 對象就有可能變得相當(dāng)臃腫。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
vuex模塊化后,需要另一個模塊的state變化,可以在這個模塊中定義getters 獲取,具體代碼如下
vuex的狀態(tài)是怎樣的,怎么改變狀態(tài)
vuex的狀態(tài)儲存在倉庫的state屬性中,state是只讀的,無法直接修改必須調(diào)用mutation才能修改
你在項目中哪里使用vuex,vuex的應(yīng)用場景
原則:
中小型項目中,如果組件的公共狀態(tài)不多的情況下,不建議使用vuex,反而會增加代碼復(fù)雜度,想要組件通信,直接通過event bus即可,中大型項目中,多個組件公共狀態(tài)較多情況下,建議使用vuex
在項目中,多個組件的公共狀態(tài)可以存儲的vuex中,比如電商網(wǎng)站的購物車數(shù)據(jù),可以存儲在vuex中。后臺管理角色鑒權(quán)中的 不同角色的側(cè)邊欄數(shù)據(jù),以及 不同角色可以訪問的路由數(shù)據(jù)可以存儲的vuex中,拿到數(shù)據(jù)儲存。