## 一:自定義事件$emit
```
this.$emit('事件名','傳遞的數(shù)據(jù)')
//例如定義了一個onChange事件,并且傳遞了一個數(shù)組
this.$emit('onChange',[0,1,2,3,4])
```
## 二:自定義組件的`v-model`
```
<input v-model="searchText">
```
等價于:
```
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
```
當(dāng)用在組件上時,`v-model`則會這樣:
```
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
```
為了讓它正常工作,這個組件內(nèi)的`<input>`必須:
* 將其`value`特性綁定到一個名叫`value`的 prop 上
* 在其`input`事件被觸發(fā)時,將新的值通過自定義的`input`事件拋出
寫成代碼之后是這樣的:
~~~
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
? ? ?v-on:input="$emit('input', $event.target.value)"
? ?>
`
})
~~~
現(xiàn)在`v-model`就應(yīng)該可以在這個組件上完美地工作起來了:
~~~
<custom-input v-model="searchText"></custom-input>
~~~
## 三:綁定原生事件到組件
在組件的根元素綁定原生事件,只需要使用`v-on`的`.native`修飾符:
```
<base-input v-on:focus.native="onFocus"></base-input>
```
但是當(dāng)組件的根元素不具備一些DOM事件,但是根元素內(nèi)部元素具備相對應(yīng)的DOM事件,那么可以使用$listeners獲取父組件傳遞進(jìn)來的所有事件函數(shù),再通過v-on="xxxx"綁定到相對應(yīng)的內(nèi)部元素上即可。
```
<base-input v-model="name" v-on:click.native="click" v-on:focus="focus" ></base-input>
```
因?yàn)閌base-input`的根元素是一個`label`元素,所以默認(rèn)情況下使用`v-on:focus`是無效的,所以需要配合`$listeners`使用,該屬性可以把事件的監(jiān)聽指向組件中某個特定的元素
> 注意:如果父級的事件添加了.native修飾符,在$listeners中不會體現(xiàn)出來的
```
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` 將所有的對象合并為一個新對象
return Object.assign({},
// 我們從父級添加所有的監(jiān)聽器
this.$listeners,
// 然后我們添加自定義監(jiān)聽器,
// 或覆寫一些監(jiān)聽器的行為
{
// 這里確保組件配合 `v-model` 的工作
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners" //focus事件將會作用于input元素
>
</label>
`
})
```
## 四:`.sync` 修飾符
在有些情況下,我們可能需要對一個 prop 進(jìn)行“雙向綁定”。不幸的是,真正的雙向綁定會帶來維護(hù)上的問題,因?yàn)樽咏M件可以修改父組件,且在父組件和子組件都沒有明顯的改動來源。
這也是為什么我們推薦以`update:myPropName`的模式觸發(fā)事件取而代之。舉個例子,在一個包含`title`prop 的假設(shè)的組件中,我們可以用以下方法表達(dá)對其賦新值的意圖:
> update:myPropName的形式是指自定義事件名為`update:屬性名稱`
~~~,
this.$emit('update:title', newTitle)
~~~
然后父組件可以監(jiān)聽那個事件并根據(jù)需要更新一個本地的數(shù)據(jù)屬性。例如:
~~~
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
~~~
為了方便起見,我們?yōu)檫@種模式提供一個縮寫,即`.sync`修飾符:
~~~
<text-document v-bind:title.sync="doc.title"></text-document>
~~~
**使用`.sync`修飾符實(shí)現(xiàn)"雙向綁定"需要滿足以下條件**
* 在子組件中需要使用`update:myPropName`的形式定義自定義事件,例如:
~~~,
this.$emit('update:title', newTitle)
~~~
* 在父組件中使用`:title.sync="title"`的形式,無需在傳入`title`這個Porp
```
<text-document v-bind:title.sync="doc.title"></text-document>
```
- 目錄結(jié)構(gòu)
- 指令
- 條件渲染
- 列表渲染
- 自定義指令
- 修飾符
- 組件
- 生命周期
- 計(jì)算屬性和監(jiān)聽屬性
- 全局注冊和局部注冊
- 動態(tài)組件
- 異步組件
- 插槽
- Prop
- 自定義事件
- 訪問元素 & 組件
- 混入
- 渲染函數(shù)
- JSX
- 組件的依賴注入
- 遞歸組件
- 路由
- 命名路由
- 路由組件傳參
- 路由守衛(wèi)
- 網(wǎng)絡(luò)請求
- 表單
- 狀態(tài)管理器
- State
- Getter
- Mutation
- Action
- Module
- CLI命令
- 安裝Vue CLI
- 創(chuàng)建Vue項(xiàng)目
- 啟動應(yīng)用
- 相關(guān)概念
- 對象解構(gòu)賦值
