1、Vue雙向數(shù)據(jù)綁定的原理
vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過(guò)Object.defineProperty()來(lái)劫持各個(gè)屬性的setter,getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽(tīng)回調(diào)。
具體步驟:(1)第一步:需要observe(發(fā)布者)的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷,包括子屬性對(duì)象的屬性,都加上 setter和getter這樣的話,給這個(gè)對(duì)象的某個(gè)值賦值,就會(huì)觸發(fā)setter,那么就能監(jiān)聽(tīng)到了數(shù)據(jù)變化 (2) 第二步:compile解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽(tīng)數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖 (3)第三步:Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是:1、在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己 2、自身必須有一個(gè)update()方法3、待屬性變動(dòng)dep.notice()通知時(shí),能調(diào)用自身的update()方法,并觸發(fā)Compile中綁定的回調(diào),則功成身退。(4)第四步:MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile和Watcher三者,通過(guò)Observer來(lái)監(jiān)聽(tīng)自己的model數(shù)據(jù)變化,通過(guò)Compile來(lái)解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達(dá)到數(shù)據(jù)變化 -> 視圖更新;視圖交互變化(input) -> 數(shù)據(jù)model變更的雙向綁定效果。
2、Vue虛擬DOM樹(shù)的原理
在大型項(xiàng)目中,不斷的改變DOM,開(kāi)銷(xiāo)非常大;希望以最小的修改量實(shí)現(xiàn)DOM樹(shù)的更新。(維護(hù)狀態(tài),更新視圖)
原理步驟:(Virtual DOM 本質(zhì)上就是在 JS 和 DOM 之間做了一個(gè)緩存,只將變更寫(xiě)入DOM)
(1)用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹(shù)的結(jié)構(gòu);然后用這個(gè)樹(shù)構(gòu)建一個(gè)真正的 DOM 樹(shù),插到文檔當(dāng)中
(2)當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹(shù)。然后用新的樹(shù)和舊的樹(shù)進(jìn)行比較,記錄兩棵樹(shù)差異
(3)把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹(shù)上,視圖就更新了
注意:視圖的結(jié)構(gòu)確實(shí)是整個(gè)全新渲染了,但是最后操作DOM的時(shí)候確實(shí)只變更有不同的地方
Virtual DOM 的 diff 算法只對(duì)同級(jí)元素進(jìn)行對(duì)比;Virtual DOM 算法主要是實(shí)現(xiàn)上面步驟的三個(gè)函數(shù):element,diff,patch。
原地復(fù)用,用key值解決。(同級(jí)中相同的節(jié)點(diǎn)類(lèi)型會(huì)復(fù)用)
https://www.zhihu.com/question/29504639/answer/73607810
https://blog.csdn.net/yczz/article/details/51292169
3、Vue-router如何實(shí)現(xiàn)路由跳轉(zhuǎn)的
(1)監(jiān)控路由變化的history對(duì)象
安裝插件\根據(jù)路由配置生成router實(shí)例?\將router實(shí)例傳入根vue實(shí)例?
(2)主動(dòng)觸發(fā)<router-link>??
router-link綁定了click方法,觸發(fā)history.push或者h(yuǎn)istory.replace,從而觸發(fā)history.transitionTo 同時(shí)會(huì)監(jiān)控hashchange和popstate來(lái)對(duì)路由變化作對(duì)用的處理
4、Vuex的狀態(tài)管理的流程

在Vue組件中dispatch actions,action中commit mutations,mutations是唯一可以觸發(fā)state中數(shù)據(jù)狀態(tài)更新的方法。
5、Vue的生命周期鉤子函數(shù)有哪些,mouted鉤子和created鉤子不同
總共分為8個(gè)階段創(chuàng)建前/后,載入前/后,更新前/后,銷(xiāo)毀前/后。
創(chuàng)建前/后: 在beforeCreated階段,vue實(shí)例的掛載元素$el和數(shù)據(jù)對(duì)象data都為undefined,還未初始化。在created階段,vue實(shí)例的數(shù)據(jù)對(duì)象data有了,$el還沒(méi)有。載入前/后:在beforeMount階段,vue實(shí)例的$el和data都初始化了,但還是虛擬的dom節(jié)點(diǎn),data.message還未替換。在mounted階段,vue實(shí)例掛載完成,data.message成功渲染。更新前/后:當(dāng)data變化時(shí),會(huì)觸發(fā)beforeUpdate和updated方法。銷(xiāo)毀前/后:在執(zhí)行destroy方法后,對(duì)data的改變不會(huì)再觸發(fā)周期函數(shù),說(shuō)明此時(shí)vue實(shí)例已經(jīng)解除了事件監(jiān)聽(tīng)以及和dom的綁定,但是dom結(jié)構(gòu)依然存在。
6、Vue父子間通信
(1)子組件使用props:[]暴露出屬性,父組件直接傳值修改props——父向子傳值
(2)自定義事件:在子組件的實(shí)現(xiàn)方法中利用this.$emit("a")觸發(fā)a事件,當(dāng)父組件調(diào)用子組件時(shí),直接在該子組件上@a進(jìn)行觸發(fā)——子向父?jìng)髦?/p>

7、用Vue實(shí)現(xiàn)一個(gè)非父子組件間的點(diǎn)擊改變對(duì)方背景色或者改變對(duì)方內(nèi)容;再用Jquery實(shí)現(xiàn);并將Vue和Jquery進(jìn)行對(duì)比




過(guò)程:(1)新建Vue對(duì)象(2)將父組件的id掛載到el上(3)用data填充數(shù)據(jù),massage,活動(dòng)的class一會(huì)style信息等(4)添加method方法
注意:對(duì)css的操作可以通過(guò)綁定class或者綁定style。
以下時(shí)Jquery方法(樣式同上):

區(qū)別:
Vue直接操作視圖層,不需要操作DOM節(jié)點(diǎn),我們只需要關(guān)注邏輯,完全實(shí)現(xiàn)了視圖層和邏輯層的解耦;
Jquery的操作是基于DOM節(jié)點(diǎn)的操作,它的優(yōu)勢(shì)在于良好的封裝和兼容,使調(diào)用簡(jiǎn)單方便。
8、Vue中的請(qǐng)求代碼應(yīng)該放在組件的method中還是Vuex的action中?你是怎么做的?
我在項(xiàng)目中的做法:將登陸請(qǐng)求以及對(duì)返回?cái)?shù)據(jù)的處理寫(xiě)在業(yè)務(wù)組件的method中,將姓名和郵箱信息等利用localstorage中,放到vuex的module中處理,其它頁(yè)面需要顯示相關(guān)信息時(shí),取得數(shù)據(jù)即可。因?yàn)檫@是組件自己的請(qǐng)求,放在method中是沒(méi)問(wèn)題的,不存在復(fù)用問(wèn)題。
我個(gè)人的思考是:大型項(xiàng)目中,要實(shí)現(xiàn)代碼復(fù)用,可以將請(qǐng)求封裝到Actions中,業(yè)務(wù)代碼邏輯中只有對(duì)Actions的調(diào)用操作,將請(qǐng)求返回的數(shù)據(jù)處理好之后傳入mutations中,mutations中僅僅是對(duì)數(shù)據(jù)進(jìn)行增刪改的處理,然后映射到state中。在組件中dispatch Actions后,異步commit mutations,直接改變state中的數(shù)據(jù),state中的數(shù)據(jù)變化直接觸發(fā)View視圖的更新,符合數(shù)據(jù)流的走向。
9、Vue中computed、method和watch的區(qū)別?
computed計(jì)算屬性:HTML DOM加載完成后立即執(zhí)行,相當(dāng)于賦值。計(jì)算屬性是根據(jù)依賴(lài)進(jìn)行緩存的,只有當(dāng)依賴(lài)改變時(shí),才會(huì)重新計(jì)算求值;依賴(lài)不改變時(shí),不會(huì)調(diào)用該函數(shù)而是直接返回之前的值。
method屬性:需要一定的條件觸發(fā)調(diào)用后才能執(zhí)行,比如click。只要頁(yè)面重新渲染就會(huì)調(diào)用method中的函數(shù)。
PS:當(dāng)一個(gè)性能開(kāi)銷(xiāo)很大的計(jì)算屬性A,要遍歷很大的數(shù)組,又有別的計(jì)算屬性依賴(lài)于A,這時(shí),利用計(jì)算屬性的緩存原理,可以避免多次重復(fù)計(jì)算。這種情況下顯然不適合用method。
watch偵聽(tīng)器:(自定義偵聽(tīng)器)Vue 通過(guò)?watch?選項(xiàng)提供了一個(gè)更通用的方法,來(lái)響應(yīng)數(shù)據(jù)的變化。當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí),這個(gè)方式是最有用的。
10、為什么要使用key?
key是Vue中識(shí)別節(jié)點(diǎn)的通用機(jī)制;頁(yè)面更新重新渲染時(shí),同一級(jí)的節(jié)點(diǎn)默認(rèn)是原地復(fù)用的渲染規(guī)則。
key 的特殊屬性主要用在 Vue的虛擬DOM算法,在新舊nodes對(duì)比時(shí)辨識(shí)VNodes。如果不使用key,Vue會(huì)使用一種最大限度減少動(dòng)態(tài)元素并且盡可能的嘗試修復(fù)/再利用相同類(lèi)型元素的算法(如果數(shù)據(jù)項(xiàng)的順序被改變,Vue 將不會(huì)移動(dòng) DOM 元素來(lái)匹配數(shù)據(jù)項(xiàng)的順序, 而是簡(jiǎn)單復(fù)用此處每個(gè)元素,并且確保它在特定索引下顯示已被渲染過(guò)的每個(gè)元素。)。使用key,它會(huì)基于key的變化重新排列元素順序,并且會(huì)移除key不存在的元素。(高效更新虛擬DOM)
有相同父元素的子元素必須有獨(dú)特的key。重復(fù)的key會(huì)造成渲染錯(cuò)誤。