本節主要時對Vue官網內容進行補充。
> 我自己第一次學習Vue官網的時,由于很多概念以及用法不清楚,導致剛剛上手時遇到了一些困難。希望通過本章對某些自認為比較難理解的概念,以及后期開發中可以會涉及到的知識點進行擴展描述,希望對你有所幫助。
## 1 內容分發(slot插槽)
我們都知道向子組件傳遞數據可以通過綁定porps屬性。如果我們現在有這樣一個需求:
> 需要將一段HTML代碼片段傳遞給子組件,并且在相應的子組件template中顯示這一段HTML內容。
你會怎么做?
```js
// 第一步: 將HTML代碼轉成String字符串
// 第二步: 將字符串通過綁定 props 傳給子組件
// 第三布:用字符串替換子組件相應位置元素的innrHTML
```
是不是覺得很麻煩?這時你就可以使用vue提供的slot元素。
```
// 在child組件的模板中你可能會這樣寫
<div class="child">
<slot>當你在父組件中沒有寫內容時,你會看到這句話!!</slot>
</div>
```
```
// 調用方式一: 父組件中
<child></child>
// ----------------------
// 渲染結果
<div class="child">
當你在父組件中沒有寫內容時,你會看到這句話!!
</div>
```
```
// 調用方式二: 父組件中
<child>
我這是在父組件中寫的東東!!
</child>
// --------------------------------
// 渲染結果
<div class="child">
我這是在父組件中寫的東東!!
</div>
```
#### 作用域插槽
在父組件中可以獲得子組件的數據
```
// child-component
<div class="child">
<slot text="hello from child"></slot>
</div>
//parent-component
<div class="parent">
<child>
<template slot-scope="props">
<span>hello from parent</span>
<span>{{ props.text }}</span> // hello from child
</template>
</child>
</div>
```
## 2 is
#### 功能之一:解除DOM 模板限制
> 有些 HTML 元素,諸如` <ul>`、`<ol>`、`<table>` 和 `<select>`,對于哪些元素可以出現在其內部是有嚴格限制的。而有些元素, 諸如 `<li>`、`<tr> `和 `<option>`,只能出現在其它某些特定的元素內部。
這會導致我們使用這些有約束條件的元素時遇到一些問題。例如:
```
<table>
<blog-post-row></blog-post-row>
</table>
```
這個自定義組件 `<blog-post-row> `會被作為無效的內容提升到外部,并導致最終渲染結果出錯。幸好這個特殊的` is `特性給了我們一個變通的辦法:
```
<table>
<tr is="blog-post-row"></tr>
</table>
```
#### 功能之二:動態組件
------------------
## 3 vm.$nextTick()
#### 什么是Vue.nextTick()
**官方文檔解釋如下:**

總得來說
>Vue 在修改數據后,視圖不會立刻更新,而是等同一事件循環中的所有數據變化完成之后,再統一進行視圖更新。
通過Promise實現nextTick。當不支持Promise時,Vue底層通過setTimeout來實現。
> 因此,在代碼中通過setTimeout可以實現相同功能。有人測試過,設置50ms的定時器是一個最佳值。
>個人感覺 setTimeout 比 nextTick 好用。在項目開發中,如遇到 nextTick 不好使情況下,嘗試 用 setTimeout 來替換。注意,setTimeou 的回調函數應該使用 `() => {} ` 形式,否側會出現this指向問題。
#### 為什么用Vue.nextTick()
> Vue是異步執行dom更新的,一旦觀察到數據變化,Vue就會開啟一個隊列,然后把在同一個事件循環 (event loop) 當中觀察到數據變化的 watcher 推送進這個隊列。如果這個watcher被觸發多次,只會被推送到隊列一次。這種緩沖行為可以有效的去掉重復數據造成的不必要的計算和DOm操作。而在下一個事件循環時,Vue會清空隊列,并進行必要的DOM更新。

> 當你設置 vm.someData = 'new value',DOM 并不會馬上更新,而是在異步隊列被清除,也就是下一個事件循環開始時執行更新時才會進行必要的DOM更新。如果此時你想要根據更新的 DOM 狀態去做某些事情,就會出現問題。為了在數據變化之后等待 Vue 完成更新 DOM ,可以在數據變化之后立即使用 Vue.nextTick(callback) 。這樣回調函數在 DOM 更新完成后就會調用
#### 注需要意
在 created 和 mounted 階段,如果需要操作渲染后的試圖,也要使用 nextTick 方法。官方文檔說明:
> 注意 mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick 替換掉 mounted
## 4 computed vs watch
> 相同: computed和watch都起到監聽/依賴一個數據,并進行處理的作用
>
> 異同:它們其實都是vue對監聽器的實現,只不過computed主要用于對同步數據的簡單處理。watch則主要用于數據輸入時異步操作或者開銷較大的情況。**能用computed的時候優先用computed**,避免了多個數據影響其中某個數據時多次調用watch的尷尬情況。**對于視圖層的改變則優先使用watch**。
>
## 5 vm.$refs操作DOM
>一個對象,持有注冊過 ref 特性 的所有 DOM 元素和組件實例。
```
<div ref="myDiv">
xxx
</div>
// 在組件中,獲取div myDiv元素
console.log(this.$refs.myDiv)
```
`ref`屬性不僅可以用在原生DOM元素上,還可以用在自定義的組件中。這樣的好處就是,你可以在父組件中調用子組件的方法
```
// 調用子組件的reset()方法
this.$refs.childComponent.reset()
```
注意
> `vm.$refs` 只在組件渲染完成后才填充,并且它是非響應式的。它僅僅是一個直接操作子組件的應急方案——應當避免在模板或計算屬性中使用 $refs。