Vue Q
Tags: vue
Published: 2020-02-24 01:56:40


### 組件通信方式有哪些？

父子組件通信：
`props`和`event`、`v-model`、`.sync`、`ref`、`$parent`和`$children`
非父子組件通信：
`$attr`和`$listeners`、`provide`和`inject`、`eventbus`、通過根實例`$root`訪問、`vuex`、`dispatch`和`brodcast`

[vue組件通信](https://mp.weixin.qq.com/s?__biz=Mzg2NTA4NTIwNA==&mid=2247484468&idx=1&sn=3c309945992fe4f0c6276d91d7cb67b8&chksm=ce5e364ff929bf59ae686e3fa2412632348d6e190054e0b83bed11b5fd851ebbe8d326b5caf0&token=1424393752&lang=zh_CN#rd)


### 子組件為什麼不可以修改父組件傳遞的Prop？

Vue提倡 **單向數據流** ,即父級props的更新會流向子組件,但是反過來則不行。這是為了防止意外的改變父組件狀態，使得應用的數據流變得難以理解。如果破壞了單向數據流，當應用複雜時，debug的成本會非常高。


###　v-model是如何實現雙向綁定的？

v-model是用來在表單控件或者組件上創建雙向綁定的，
v-model的本質是‵v-bind‵和‵v-on‵的語法糖，在一個組件上使用v-model，默認會為組件綁定名為value的prop和名為input的事件。


### Vuex和單純的全局對像有什麼區別？

Vuex和全局對象主要有兩大區別：

1. `Vuex` 的狀態存儲是 **響應式** 的。當Vue組件從store中讀取狀態的時候，若store中的狀態發生變化，那麼相應的組件也會相應地得到高效更新。
2. 不能直接改變store 中的狀態。改變store中的狀態的 **唯一途徑** 就是顯式地提交(commit) 
 **mutation** 。這樣使得我們可以方便地跟踪每一個狀態的變化，從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。


### 為什麼Vuex 的mutation 中不能做異步操作？

如果mutation支持異步操作，就沒有辦法知道狀態是何時更新的，[無法很好的進行狀態的追踪](https://www.zhihu.com/question/48759748/answer/112823337)，給調試帶來困難。

![Alt vuex](https://vuex.vuejs.org/vuex.png "vuex")

### action和mutaction的區別：

Action 類似於 mutation，不同在於：

Action 提交的是 mutation，而不是直接變更狀態。
Action 可以包含任意異步操作。
說簡單點就是mutation用於同步執行，action用於異步執行，可以多重分發mutation。


## 生命周期

### vue組件有哪些聲明周期鉤子？

beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
[`<keep-alive>`](https://vuejs.org/v2/guide/components-dynamic-async.html)有自己獨立的鉤子函數`activated`和`deactivated`。

### Vue 的父組件和子組件生命週期鉤子執行順序是什麼？


#### 渲染過程： 

父組件掛載完成一定是等子組件都掛載完成後，才算是父組件掛載完，所以父組件的mounted在子組件mouted之後
父beforeCreate ->父created ->父beforeMount ->(子beforeCreate ->子created ->子beforeMount ->子mounted )->父mounted

#### 子組件更新過程：

影響到父組件： 父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
不影響父組件： 子beforeUpdate -> 子updated

#### 父組件更新過程：

影響到子組件： 父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
不影響子組件： 父beforeUpdate -> 父updated

銷毀過程： 
父beforeDestroy ->子beforeDestroy ->子destroyed ->父destroyed
看起來很多好像很難記憶，其實只要理解了，不管是哪種情況，都一定是父組件等待子組件完成後，才會執行自己對應完成的鉤子，就可以很容易記住。

##  相似屬性對比

###  v-show 和v-if 有哪些區別？

`v-if`會在切換過程中對條件塊的事件監聽器和子組件進行銷毀和重建，如果初始條件是false，則什麼都不做，直到條件第一次為true時才開始渲染模塊。

`v-show`只是基於css進行切換，不管初始條件是什麼，都會渲染。
所以，v-if切換的開銷更大，而v-show初始化渲染開銷更大，在需要頻繁切換，或者切換的部分dom很複雜時，使用`v-show`更合適。渲染後很少切換的則使用`v-if`更合適。

### computed 和watch 有什麼區別？

`computed`計算屬性，是依賴其他屬性的計算值，並且 **有緩存** ，只有當依賴的值變化時才會更新。
`watch`是在監聽的屬性發生變化時，在回調中執行一些邏輯。

所以，computed適合在模板渲染中，某個值是依賴了其他的響應式對象甚至是計算屬性計算而來，而watch適合監聽某個值的變化去完成一段複雜的業務邏輯。

### computed vs methods

計算屬性是基於他們的響應式依賴進行緩存的，只有在依賴發生變化時，才會計算求值，而使用methods，每次都會執行相應的方法。

### keep-alive 的作用是什麼？

`keep-alive`可以在組件切換時，保存其包裹的組件的狀態，使其不被銷毀， **防止多次渲染** 。
其擁有兩個獨立的生命週期鉤子函數actived和deactived，使用keep-alive包裹的組件在切換時不會被銷毀，而是緩存到內存中並執行deactived鉤子函數，命中緩存渲染後會執行actived鉤子函數。

### Vue 中v-html 會導致什麼問題

在網站上動態渲染任意HTML，很容易導致XSS 攻擊。所以只能在可信內容上使用v-html，且永遠不能用於用戶提交的內容上。

## 原理分析

[如何追踪变化](https://cn.vuejs.org/v2/guide/reactivity.html#%E5%A6%82%E4%BD%95%E8%BF%BD%E8%B8%AA%E5%8F%98%E5%8C%96)

![Alt reactivity](https://cn.vuejs.org/images/data.png "data")

Vue的響應式是通過`Object.defineProperty`對數據進行劫持，並結合觀察者模式實現。Vue利用Object.defineProperty創建一個`observe`來劫持監聽所有的屬性，把這些屬性全部轉為`getter`和`setter`。Vue中每個組件實例都會對應一個`watcher`實例，它會在組件渲染的過程中把使用過的數據屬性通過getter收集為依賴。之後當依賴項的setter觸發時，會通知watcher，從而使它關聯的組件重新渲染。




### Vue中如何檢測數組變化？

Vue的Observer對數組做了單獨的處理，對數組的方法進行編譯，並賦值給數組屬性的`__proto__`屬性上，因為`原型鏈的機制`，找到對應的方法就不會繼續往上找了。編譯方法中會對一些會增加索引的方法（push，unshift，splice）進行手動observe。



### 組件的data 為什麼要寫成函數形式？

Vue的組件都是 **可複用的** ，一個組件創建好後，可以在多個地方復用，而不管復用多少次，組件內的data都應該是相互隔離，互不影響的，所以組件每復用一次，data就應該復用一次，每一處復用組件的data改變應該對其他復用組件的數據不影響。
為了實現這樣的效果，data就不能是單純的對象，而是以一個函數返回值的形式，所以每個組件實例可以維護獨立的數據拷貝，不會相互影響。