Vue面試總結(jié)

生命周期函數(shù)面試題

1.什么是Vue生命周期?
vue生命周期是指vue是對象從創(chuàng)建到銷毀的過程。

2.Vue生命周期的作用是什么?
在vue生命周期的不同階段通過對應(yīng)的鉤子函數(shù)來實現(xiàn)組件數(shù)據(jù)管理和DOM渲染兩大重要功能。
創(chuàng)建階段:
beforecreate:實例已經(jīng)初始化,但不能獲取DOM節(jié)點。(沒有data,沒有el)
created:實例已經(jīng)創(chuàng)建,仍然不能獲取DOM節(jié)點。(有data,沒有el)
載入階段:
beforemount:模板編譯完成,但還沒掛載到界面上。(有data,有el)
mounted:編譯好的模板已掛載到頁面中(數(shù)據(jù)和DOM都已經(jīng)渲染出來)。
更新階段:
beforeupdate:數(shù)據(jù)發(fā)生變化立即調(diào)用,此時data中數(shù)據(jù)是最新的,但頁面上數(shù)據(jù)仍然是舊的(檢測到數(shù)據(jù)更新時,但DOM更新前執(zhí)行)。
updated:更新結(jié)束后執(zhí)行,此時data中的值和頁面上的值都是最新的。
銷毀階段:
beforedestroy:當要銷毀vue實例時,在銷毀之前執(zhí)行。
destroy:在銷毀vue實例時執(zhí)行。

3.第一次頁面加載會觸發(fā)哪幾個鉤子函數(shù)?
beforeCreate, created, beforeMount, mounted。

4.簡述每個生命周期具體適合哪些場景?
beforecreate:可以加Loading事件。
create:初始化完成時的事件寫在這里,異步請求也適宜在這里調(diào)用(請求不宜過多,避免白屏?xí)r間太長)。
可以在這里結(jié)束loading事件,還做一些初始化,或?qū)崿F(xiàn)函數(shù)的自執(zhí)行。
此時未掛載DOM,若在此階段進行DOM操作一定要放在Vue.nextTick()的回調(diào)函數(shù)中。
mounted:此時完成掛載DOM和渲染,需要操作DOM的方法可以放在這里,也可在這發(fā)起后端請求,拿回數(shù)據(jù),配合路由鉤子做一些事情。
beforeupdate:可在更新前訪問現(xiàn)有的DOM,如手動移出添加的事件監(jiān)聽器。
updated:組件DOM已完成更新,可執(zhí)行依賴的DOM操作。
注意:不要在此函數(shù)中操作數(shù)據(jù)(修改屬性),會陷入死循環(huán)。
activated:在使用vue-router時有時需要使用<keep-alive></keep-alive>來緩存組件狀態(tài),這個時候created鉤子就不會被重復(fù)調(diào)用了。
如果我們的子組件需要在每次加載的時候進行某些操作,可以使用activated鉤子觸發(fā)。
deactivated:<keep-alive></keep-alive>組件被移除時使用。
beforedestroy:銷毀前,可以做一些刪除提示,如:您確定刪除xx嗎?
destroy:銷毀后,這時組件已經(jīng)沒有了,無法操作里面的任何東西了。

5.created和mounted的區(qū)別?
created:實例已經(jīng)創(chuàng)建,但不能獲取DOM節(jié)點。
mounted:模板已經(jīng)掛載到頁面上,可以操作DOM元素。

6.vue組件間通信六種方式
組件之間的傳值通信
組件之間通訊分為三種: 父傳子、子傳父、兄弟組件之間的通訊;
(1)props/$emit

  • 父傳子:props
  • 子傳父:父組件向子組件傳遞事件方法,子組件通過$emit觸發(fā)事件,回調(diào)給父組件

(2)$eimt/$on

  • 這種方法通過一個空的Vue實例作為中央事件總線(事件中心),用它來觸發(fā)事件和監(jiān)聽事件,巧妙而輕量地實現(xiàn)了任何組件間的通信,包括父子、兄弟、跨級。
    具體實現(xiàn)方式:
  var Event=new Vue();
   Event.$emit(事件名,數(shù)據(jù));
   Event.$on(事件名,data => {});
// 假設(shè)兄弟組件有三個,分別是A、B、C組件,C組件如何獲取A或者B組件的數(shù)據(jù)
// 組件A、B通過Event.$emit(事件名,數(shù)據(jù))將數(shù)據(jù)傳遞,組件C通過 Event.$on(事件名,data => {})接受組件A、B傳遞的數(shù)據(jù)

(3)Vuex

  • vuex 就是一個倉庫,倉庫里放了很多對象。在state中存放數(shù)據(jù)源,當組件要更改state中的數(shù)據(jù)時,必須通過mutation進行,mutation儲存的是改變state中數(shù)據(jù)的操作方法,之后通過actions儲存的操作去觸發(fā)mutation中的方法,由組件中的$store.dispatch('action 名稱', data1)來觸發(fā)。然后由commit()來觸發(fā)mutation的調(diào)用 , 間接更新 state。

(4)Vuex + localstorage

  • vuex 是 vue 的狀態(tài)管理器,存儲的數(shù)據(jù)是響應(yīng)式的。但是并不會保存起來,刷新之后就回到了初始狀態(tài),具體做法應(yīng)該在vuex里數(shù)據(jù)改變的時候把數(shù)據(jù)拷貝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的數(shù)據(jù),取出來再替換store里的state。
  • 這里需要注意的是:由于vuex里,我們保存的狀態(tài),都是數(shù)組,而localStorage只支持字符串,所以需要用JSON轉(zhuǎn)換。

(5)$attrs/$listeners

  • $attrs:包含了父作用域中不作為 prop 被識別 (且獲取) 的 attribute 綁定 (class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級別的組件時非常有用。
  • $listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時非常有用。

(6)provide/inject

  • provide/inject:vue2.2.0 新增API,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時間里始終生效。
  • 總而言之:祖先組件中通過provider來提供變量,然后在子孫組件中通過inject來注入變量。
  • provide / inject API主要解決了跨級組件間的通信問題,不過它的使用場景,主要是子組件獲取上級組件的狀態(tài),跨級組件間建立了一種主動提供與依賴注入的關(guān)系。
// A.vue
export default {
 provide: {
   name: 'nora'
 }
}
/**************************************/
// B.vue
export default {
 inject: ['name'],
 mounted () {
   console.log(this.name);  // nora
 }
}
  • 需要注意的是:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個可監(jiān)聽的對象,那么其對象的屬性還是可響應(yīng)的----vue官方文檔
    provide與inject 怎么實現(xiàn)數(shù)據(jù)響應(yīng)式?
    使用2.6最新API Vue.observable 優(yōu)化響應(yīng)式 provide(推薦)

  • 我們來看個例子:孫組件D、E和F獲取A組件傳遞過來的color值,并能實現(xiàn)數(shù)據(jù)響應(yīng)式變化,即A組件的color變化后,組件D、E、F會跟著變(核心代碼如下:)

//A組件
<div>
     <h1>A 組件</h1>
     <button @click="() => changeColor()">改變color</button>
     <ChildrenB />
     <ChildrenC />
</div>
......
// provide() {
 //   return {
 //     theme: {
 //       color: this.color //這種方式綁定的數(shù)據(jù)并不是可響應(yīng)的
 //     } // 即A組件的color變化后,組件D、E、F不會跟著變
 //   };
 // },

// 方法二:使用2.6最新API Vue.observable 優(yōu)化響應(yīng)式 provide
provide() {
   this.theme = Vue.observable({
      color: "blue"
    });
    return {
      theme: this.theme
    };
  },
  methods: {
    changeColor(color) {
      if (color) {
        this.theme.color = color;
      } else {
        this.theme.color = this.theme.color === "blue" ? "red" : "blue";
      }
    }
  }
/******************************************************************/
// F 組件 
<template functional>
 <div class="border2">
   <h3 :style="{ color: injections.theme.color }">F 組件</h3>
 </div>
</template>
<script>
export default {
 inject: {
   theme: {
     //函數(shù)式組件取值不一樣
     default: () => ({})
   }
 }
};
</script>

(7)$parent / $children與 ref

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例
  • $parent / $children:訪問父 / 子實例
  • 需要注意的是:這兩種都是直接得到組件實例,使用后可以直接調(diào)用組件的方法或訪問數(shù)據(jù)。
  • $parent :訪問父實例,如果當前實例有的話。
  • $children:當前實例的直接子組件。需要注意 $children并不保證順序,也不是響應(yīng)式的。如果你發(fā)現(xiàn)自己正在嘗試使用 $children來進行數(shù)據(jù)綁定,考慮使用一個數(shù)組配合 v-for 來生成子組件,并且使用 Array 作為真正的來源。
  • 這兩種方法的弊端是,無法在跨級或兄弟間通信。
// component-a 子組件
export default {
 data () {
   return {
     title: 'Vue.js'
   }
 },
 methods: {
   sayHello () {
     window.alert('Hello');
   }
 }
}
/***********************************/
// 父組件
<template>
 <component-a ref="comA"></component-a>
</template>
<script>
 export default {
   mounted () {
     const comA = this.$refs.comA;
     console.log(comA.title);  // Vue.js
     comA.sayHello();  // 彈窗
   }
 }
</script>

原文參考: vue組件間通信六種方式

7.vuex是什么?怎么使用?哪種功能場景使用它?

  • vuex 就是一個倉庫,倉庫里放了很多對象。
  • 其中 state 存放的是數(shù)據(jù)狀態(tài),不可以直接修改里面的數(shù)據(jù)。
  • getters類似vue的計算屬性,主要用來過濾一些數(shù)據(jù)。
  • mutations:存放的是動態(tài)修改Vuex的state中保存的數(shù)據(jù)狀態(tài)的方法。
  • actions:保存的觸發(fā)mutations中方法的方法,可以理解為通過將mutations里面處里數(shù)據(jù)的方法變成可異步的處理數(shù)據(jù)的方法,簡單的說就是異步操作數(shù)據(jù)。

一般什么樣的數(shù)據(jù)會放在 State 中呢?
目前主要有兩種數(shù)據(jù)會使用 vuex 進行管理: 1、組件之間全局共享的數(shù)據(jù) 2、通過后端異步請求的數(shù)據(jù) 比如做加入購物車、登錄狀態(tài)等都可以使用Vuex來管理數(shù)據(jù)狀態(tài)

  • 怎么使用Vuex? 在main.js引入store,注入。新建了一個目錄store,… export
  • 場景有:單頁應(yīng)用中,組件之間的狀態(tài)、音樂播放、登錄狀態(tài)、加入購物車

8.開發(fā)時,改變數(shù)組或者對象的數(shù)據(jù),但是頁面沒有更新如何解決?

  • 對于數(shù)組:
    Vue 不能檢測以下數(shù)組的變動:
    1.當你利用索引直接設(shè)置一個數(shù)組項時,例如:vm.items[indexOfItem] = newValue
    2.當你修改數(shù)組的長度時,例如:vm.items.length = newLength
//舉個例子:
var vm = new Vue({
 data: {
   items: ['a', 'b', 'c']
 }
})
vm.items[1] = 'x' // 不是響應(yīng)性的
vm.items.length = 2 // 不是響應(yīng)性的

//為了解決第一類問題,以下兩種方式都可以實現(xiàn)和 vm.items[indexOfItem] = newValue 相同的效果,同時也將在響應(yīng)式系統(tǒng)內(nèi)觸發(fā)狀態(tài)更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
// 你也可以使用 [`vm.$set`](https://cn.vuejs.org/v2/api/#vm-set) 實例方法,該方法是全局方法 `Vue.set` 的一個別名:
vm.$set(vm.items, indexOfItem, newValue)
// 為了解決第二類問題,你可以使用 `splice`:
vm.items.splice(newLength)
var vm = new Vue({
 data: {
   userProfile: {
     name: 'Anika'
   }
 }
})

//你可以添加一個新的 age 屬性到嵌套的 userProfile 對象:
Vue.set(vm.userProfile, 'age', 27)
//你還可以使用 vm.$set 實例方法,它只是全局 Vue.set 的別名:
vm.$set(vm.userProfile, 'age', 27)
//有時你可能需要為已有對象賦予多個新屬性,比如使用 Object.assign() 或 _.extend()。在這種情況下,你應(yīng)該用兩個對象的屬性創(chuàng)建一個新的對象。
vm.userProfile = Object.assign({}, vm.userProfile, {
 age: 27,
 favoriteColor: 'Vue Green'
})

9.vue彈窗后如何禁止?jié)L動條滾動?
參考原文:
vue彈窗屏蔽滑動的兩種解決方案
vue彈窗后如何禁止?jié)L動條滾動?
vue如何禁止彈窗后面的滾動條滾動?

10.如何在 vue 項目里正確地引用 jquery 和 jquery-ui的插件
參考原文:
如何在 vue 項目里正確地引用 jquery 和 jquery-ui的插件
詳解如何在 vue 項目里正確地引用 jquery 和 jquery-ui的插件

11.nextTick

  • nextTick可以讓我們在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào),用于獲得更新后的 DOM
  • nextTick主要使用了宏任務(wù)和微任務(wù)。根據(jù)執(zhí)行環(huán)境分別嘗試采用
    Promise
    MutationObserver
    setImmediate
    如果以上都不行則采用setTimeout
  • 定義了一個異步方法,多次調(diào)用nextTick會將方法存入隊列中,通過這個異步方法清空當前隊列

12.computedwatch區(qū)別

  • computed是計算屬性,具有緩存性。
    當頁面中有某些數(shù)據(jù)依賴其他數(shù)據(jù)進行變動的時候,可以使用計算屬性computed。
    用于依賴發(fā)生變化時,觸發(fā)屬性重新計算。
    Computed本質(zhì)是一個具備緩存的watcher,依賴的屬性發(fā)生變化就會更新視圖。 適用于計算比較消耗性能的計算場景。
  • watch更多的是「觀察」的作用,類似于某些數(shù)據(jù)的監(jiān)聽回調(diào),用于觀察props,$emit或者本組件的值,當數(shù)據(jù)變化時來執(zhí)行回調(diào)進行后續(xù)操作。
    無緩存性,頁面重新渲染時值不變化也會執(zhí)行。
    Watch沒有緩存性,更多的是觀察的作用,可以監(jiān)聽某些數(shù)據(jù)執(zhí)行回調(diào)。當我們需要深度監(jiān)聽對象中的屬性時,可以打開deep:true選項,這樣便會對對象中的每一項進行監(jiān)聽。這樣會帶來性能問題,優(yōu)化的話可以使用字符串形式監(jiān)聽,如果沒有寫到組件中,不要忘記使用unWatch手動注銷。
  • 應(yīng)用場景:
    當我們要進行數(shù)值計算,而且依賴于其他數(shù)據(jù),那么把這個數(shù)據(jù)設(shè)計為computed。
    如果你需要在某個數(shù)據(jù)變化時做一些事情,使用watch來觀察這個數(shù)據(jù)變化。

13.對于MVVM的理解

  • MVVM 是 Model-View-ViewModel 的縮寫
  • Model:表數(shù)據(jù)模型,因為它僅僅關(guān)注數(shù)據(jù)本身,不關(guān)心任何行為
  • View:用戶操作界面,當ViewModel對Model進行更新的時候,會通過數(shù)據(jù)綁定更新到View
  • ViewModel :業(yè)務(wù)邏輯層,也是View和Model層的橋梁
  • 總結(jié):總結(jié): MVVM模式簡化了界面與業(yè)務(wù)的依賴,解決了數(shù)據(jù)頻繁更新。MVVM 在使用當中,利用雙向綁定技術(shù),使得 Model 變化時,ViewModel 會自動更新,而 ViewModel 變化時,View 也會自動變化。

14.Vue是如何實現(xiàn)雙向綁定的?

  • Observer遍歷數(shù)據(jù)對象,給所有屬性加上settergetter,監(jiān)聽數(shù)據(jù)的變化
  • compile解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁面視圖,并將每個指令對應(yīng)的節(jié)點綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動,收到通知,更新視圖
  • Watcher 訂閱者是 ObserverCompile 之間通信的橋梁,主要做的事情:
    在自身實例化時往屬性訂閱器 (dep)里面添加自己
    待屬性變動 dep.notice()通知時,調(diào)用自身的 update()方法,并觸發(fā)Compile中綁定的回調(diào)
    Vue2.x 響應(yīng)式原理
  • vue實現(xiàn)數(shù)據(jù)雙向綁定主要是:采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過 Object.defineProperty() 來劫持各個屬性的setter,getter,在數(shù)據(jù)變動時發(fā)布消息給訂閱者,觸發(fā)相應(yīng)監(jiān)聽回調(diào)。當把一個普通 Javascript 對象傳給 Vue實例來作為它的 data選項時,Vue將遍歷它的屬性,用Object.defineProperty()將它們轉(zhuǎn)為getter/setter。用戶看不到getter/setter,但是在內(nèi)部它們讓Vue追蹤依賴,在屬性被訪問和修改時通知變化。
  • vue的數(shù)據(jù)雙向綁定 將MVVM作為數(shù)據(jù)綁定的入口,整合Observer,CompileWatcher三者,通過Observer來監(jiān)聽自己的model的數(shù)據(jù)變化,通過Compile來解析編譯模板指令(vue中是用來解析 {{}}),最終利用watcher搭起observerCompile之間的通信橋梁,達到數(shù)據(jù)變化 —>視圖更新;視圖交互變化(input)—>數(shù)據(jù)model變更雙向綁定效果。
    原文參考:http://interview.poetries.top/

15.Vue的v-model雙向綁定原理?

  • v-model本質(zhì)就是一個語法糖,可以看成是value + input方法的語法糖。 可以通過model屬性的prop和event屬性來進行自定義。原生的v-model,會根據(jù)標簽的不同生成不同的事件和屬性

  • text 和 textarea 元素使用 value 屬性和 input 事件

  • checkbox 和 radio 使用 checked 屬性和 change 事件

  • select 字段將 value 作為 prop 并將 change 作為事件

  • 可以將v-model進行如下改寫:

<input v-model="sth" />
//  等同于
<input :value="sth" @input="sth = $event.target.value" />
//這個語法糖必須是固定的,也就是說屬性必須為value,方法名必須為:input。

16.ref的作用

  • 綁定到普通元素上:獲取dom元素this.$refs.box
  • 綁定到子組件上:
    獲取子組件中的data,this.$refs.box.msg
    調(diào)用子組件中的方法this.$refs.box.open()

17.導(dǎo)航守衛(wèi)?

  • 全局守衛(wèi):beforeEach,afterEach
  • 局部守衛(wèi):
    beforeRouteEnter:因為當守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建,不能獲取組件實例的this
    beforeRouteUpdate: 在當前路由改變,但是該組件被復(fù)用時調(diào)用,可以訪問組件實例 this
    beforeRouteLeave:導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用,可以訪問組件實例 this
  • 每個守衛(wèi)方法接收三個參數(shù):
    to:目標路由對象
    from:準備要離開的路由
    next():進行管道中的下一個鉤子??蓚鬟f參數(shù)有布爾值false,直接寫路徑'/'或{path:'/'},回調(diào)函數(shù)
  • 注意:后置鉤子函數(shù)afterEach不會接受next函數(shù)也不會改變導(dǎo)航本身。
  1. 12道vue高頻原理面試題,你能答出幾道?

19.$route$router的區(qū)別

  • $route是“路由信息對象”,包括path,params,hash,query,fullPath,matched,name等路由信息參數(shù)。
  • $router是“路由實例”對象包括了路由的跳轉(zhuǎn)方法,鉤子函數(shù)等

20.<keep-alive></keep-alive>的作用是什么?

  • keep-alive可以實現(xiàn)組件緩存,當組件切換時,主要用于保留組件狀態(tài)或避免重新渲染
  • 使用場景:比如有一個列表和一個詳情,那么用戶就會經(jīng)常執(zhí)行打開詳情=>返回列表=>打開詳情…這樣的話列表和詳情都是一個頻率很高的頁面,那么就可以對列表組件使用<keep-alive></keep-alive>進行緩存,這樣用戶每次返回列表的時候,都能從緩存中快速渲染,而不是重新渲染
  • 常用的兩個屬性include/exclude,允許組件有條件的進行緩存
  • 兩個生命周期activated/deactivated,用來得知當前組件是否處于活躍狀態(tài)

21.指令v-el的作用是什么?

  • 提供一個在頁面上已存在的DOM元素作為Vue實例的掛載目標

22.組件中的data為什么是一個函數(shù)?

  • 如果data是對象的話,由于對象是引用類型,組件被復(fù)用的話,就會創(chuàng)建多個實例。本質(zhì)上,這些實例用的都是同一個構(gòu)造函數(shù)。這樣就會影響到所有的實例,所以為了保證組件不同的實例之間data不沖突,data必須是一個函數(shù)。

23.Vue中的key到底有什么用?

  • key是為Vue中的vnode標記的唯一id,通過這個key,我們的diff操作可以更準確、更快速。
  • diff算法的過程中,先會進行新舊節(jié)點的首尾交叉對比,當無法匹配的時候會用新節(jié)點的key與舊節(jié)點進行比對,然后超出差異。
  • 簡單來說,主要是為了高效的更新虛擬DOM。另外vue中在使用相同標簽名元素的過渡切換時,也會使用到key屬性,其目的也是為了讓vue可以區(qū)分它們,

24.說一下vue2.x中如何監(jiān)測數(shù)組變化

  • 使用了函數(shù)劫持的方式,重寫了數(shù)組的方法,Vuedata中的數(shù)組進行了原型鏈重寫,指向了自己定義的數(shù)組原型方法。這樣當調(diào)用數(shù)組api時,可以通知依賴更新。如果數(shù)組中包含著引用類型,會對數(shù)組中的引用類型再次遞歸遍歷進行監(jiān)控。這樣就實現(xiàn)了監(jiān)測數(shù)組變化。
  • 重寫的數(shù)組API:push,pop,shiftunshift,splice,sort,reserve。

25.你的接口請求一般放在哪個生命周期中

  • 接口請求一般放在mounted中,但需要注意的是服務(wù)端渲染時不支持mounted,需要放到created

26.Vue事件綁定原理說一下

  • 原生事件綁定是通過addEventListener綁定給真實元素的,組件事件綁定是通過Vue自定義的$on實現(xiàn)的

27.Vue模版編譯原理知道嗎,能簡單說一下嗎?

  • 簡單說,Vue的編譯過程就是將template轉(zhuǎn)化為render函數(shù)的過程。
  • 會經(jīng)歷以下階段:生成AST樹(抽象語法樹) --> 優(yōu)化 --> codegen(代碼生成器)
  • (1)首先解析模版,生成AST語法樹(一種用JavaScript對象的形式來描述整個模板)。 使用大量的正則表達式對模板進行解析,遇到標簽、文本的時候都會執(zhí)行對應(yīng)的鉤子進行相關(guān)處理。
  • (2)Vue的數(shù)據(jù)是響應(yīng)式的,但其實模板中并不是所有的數(shù)據(jù)都是響應(yīng)式的。有一些數(shù)據(jù)首次渲染后就不會再變化,對應(yīng)的DOM也不會變化。那么優(yōu)化過程就是深度遍歷AST樹,按照相關(guān)條件對樹節(jié)點進行標記。這些被標記的節(jié)點(靜態(tài)節(jié)點)我們就可以跳過對它們的比對,對運行時的模板起到很大的優(yōu)化作用。
  • (3)編譯的最后一步是將優(yōu)化后的AST樹轉(zhuǎn)換為可執(zhí)行的代碼

如何從真實DOM到虛擬DOM?

  • 涉及到Vue中的模板編譯原理,主要過程:
  1. 將模板轉(zhuǎn)換成ast 樹,ast 用對象來描述真實的JS語法(將真實DOM轉(zhuǎn)換成虛擬DOM)
  2. 優(yōu)化樹
  3. 將ast 樹生成代碼

28.Vue2.x和Vue3.x渲染器的diff算法分別說一下

  • Vue2.x中的虛擬dom 是進行全量的對比。
  • Vue3.0 中新增了靜態(tài)標記(PatchFlag):在與上次虛擬結(jié)點進行對比的時候,值對比 帶有 patch flag的節(jié)點,并且可以通過 flag的信息得知當前節(jié)點要對比的具體內(nèi)容化
  1. Vue中hash模式和history模式的區(qū)別
  • 在最明顯的顯示上:hash模式的URL中會夾雜著#號,而history沒有。
  • Vue底層對它們的實現(xiàn)方式不同:
    hash模式是依靠onhashchange事件(監(jiān)聽location.hash的改變)
    history模式是主要是依靠的HTML5 history中新增的兩個方法,pushState()可以改變url地址且不會發(fā)送請求,replaceState()可以讀取歷史記錄棧,還可以對瀏覽器記錄進行修改。
window.onhashchange = function(event){
 // location.hash獲取到的是包括#號的,如"#heading-3"
 // 所以可以截取一下
  let hash = location.hash.slice(1);
}
  • 當真正需要通過URL向后端發(fā)送HTTP請求的時候,比如常見的用戶手動輸入URL后回車,或者是刷新(重啟)瀏覽器,這時候history模式需要后端的支持。因為history模式下,前端的URL必須和實際向后端發(fā)送請求的URL一致,例如有一個URL是帶有路徑path的(例如www.libai.wang/blogs/id),如果后端沒有對這個路徑做處理的話,就會返回404錯誤。所以需要后端增加一個覆蓋所有情況的候選資源,一般會配合前端給出的一個404頁面。
  1. 說說你對 proxy 的理解
    vue的數(shù)據(jù)劫持有兩個缺點:
  • 無法監(jiān)聽通過索引修改數(shù)組的值的變化
  • 無法監(jiān)聽object 也就是對象的值的變化
    所以vue2.x中才會有$set 屬性的存在
    proxyes6中推出的新 api,可以彌補以上兩個缺點,所以 vue3.x版本用 proxy 替換object.defineproperty

31.Vue 的響應(yīng)式原理中 Object.defineProperty 有什么缺陷?

  • Object.defineProperty 無法監(jiān)控到數(shù)組下標的變化,導(dǎo)致通過數(shù)組下標添加元素,不能實時響應(yīng);
  • Object.defineProperty只能劫持對象的屬性,從而需要對每個對象,每個屬性進行遍歷,如果,屬性值是對象,還需要深度遍歷。Proxy 可以劫持整個對象,并返回一個新的對象
  • Proxy 不僅可以代理對象,還可以代理數(shù)組。還可以代理動態(tài)增加的屬性

32.Proxy 相比于 defineProperty 的優(yōu)勢?

  • 數(shù)組變化也能監(jiān)聽到
  • 不需要深度遍歷監(jiān)聽
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、組件間怎么傳值,具體說說代碼怎樣實現(xiàn) 子傳父:子向父是通過 events($emit);通過父鏈 / 子鏈也可...
    chang_遇見緣閱讀 4,094評論 12 87
  • Vue優(yōu)點 數(shù)據(jù)驅(qū)動和組件化 數(shù)據(jù)驅(qū)動:自動計算屬性和追蹤依賴的模板表達 組件化:可復(fù)用,解耦的組件來構(gòu)造頁面 V...
    RayLightUp閱讀 517評論 0 5
  • 一、如何創(chuàng)建vue項目? 1.安裝node.js,并配置環(huán)境。(自行百度) 2.使用cmd安裝淘寶鏡像。(可不安裝...
    Arvin0320丶閱讀 431評論 0 1
  • Vue中,key值的作用和原理 作用 key的作用是為了在diff算法執(zhí)行時更快的找到對應(yīng)的節(jié)點,提高diff速度...
    槿琰閱讀 1,769評論 0 2
  • 夜鶯2517閱讀 128,218評論 1 9

友情鏈接更多精彩內(nèi)容