生命周期函數(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' })
- 強制刷新
this.$forceUpdate()
原文參考:https://blog.csdn.net/sunzbking/article/details/86150365
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.
computed和watch區(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ù)對象,給所有屬性加上setter和getter,監(jiān)聽數(shù)據(jù)的變化compile解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁面視圖,并將每個指令對應(yīng)的節(jié)點綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動,收到通知,更新視圖Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情:
在自身實例化時往屬性訂閱器(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,Compile和Watcher三者,通過Observer來監(jiān)聽自己的model的數(shù)據(jù)變化,通過Compile來解析編譯模板指令(vue中是用來解析{{}}),最終利用watcher搭起observer和Compile之間的通信橋梁,達到數(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)航本身。
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ù)組的方法,
Vue將data中的數(shù)組進行了原型鏈重寫,指向了自己定義的數(shù)組原型方法。這樣當調(diào)用數(shù)組api時,可以通知依賴更新。如果數(shù)組中包含著引用類型,會對數(shù)組中的引用類型再次遞歸遍歷進行監(jiān)控。這樣就實現(xiàn)了監(jiān)測數(shù)組變化。- 重寫的數(shù)組API:
push,pop,shift,unshift,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中的模板編譯原理,主要過程:
- 將模板轉(zhuǎn)換成ast 樹,ast 用對象來描述真實的JS語法(將真實DOM轉(zhuǎn)換成虛擬DOM)
- 優(yōu)化樹
- 將ast 樹生成代碼
28.Vue2.x和Vue3.x渲染器的diff算法分別說一下
Vue2.x中的虛擬dom是進行全量的對比。Vue3.0中新增了靜態(tài)標記(PatchFlag):在與上次虛擬結(jié)點進行對比的時候,值對比 帶有patch flag的節(jié)點,并且可以通過flag的信息得知當前節(jié)點要對比的具體內(nèi)容化
- 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頁面。
- 說說你對 proxy 的理解
vue的數(shù)據(jù)劫持有兩個缺點:
- 無法監(jiān)聽通過索引修改數(shù)組的值的變化
- 無法監(jiān)聽
object也就是對象的值的變化
所以vue2.x中才會有$set屬性的存在
proxy是es6中推出的新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)聽

