事件處理方式
1. v-on指令
1.直接把 JavaScript 代碼寫(xiě)在 v-on 指令中是不可行的,v-on指令需要接收一個(gè)調(diào)用的方法名稱,
<button v-on:click="greet">Greet</button>
// 在 `methods` 對(duì)象中定義方法
methods: {
greet: function (event) {
// `this` 在方法里指向當(dāng)前 Vue 實(shí)例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
2. 事件內(nèi)聯(lián)處理器
2.除此之外vue還可以使用內(nèi)聯(lián)處理器,需要在內(nèi)聯(lián)語(yǔ)句處理器中訪問(wèn)原始的 DOM 事件。可以用特殊變量 $event 把它傳入方法
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
<button v-on:click="warn('hello.', $event)">Submit</button>
// 在 `methods` 對(duì)象中定義方法
methods: {
say: function (message) {
alert(message)
},
warn: function (message, event) {
// 現(xiàn)在我們可以訪問(wèn)原生事件對(duì)象
if (event) {
event.preventDefault()
}
alert(message)
}
}
Props
所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中,但是反過(guò)來(lái)則不行。這樣會(huì)防止從子組件意外改變父級(jí)組件的狀態(tài),從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
這里有兩種常見(jiàn)的試圖改變一個(gè) prop 的情形:
- 這個(gè) prop 用來(lái)傳遞一個(gè)初始值;這個(gè)子組件接下來(lái)希望將其作為一個(gè)本地的 prop 數(shù)據(jù)來(lái)使用。在這種情況下,最好定義一個(gè)本地的 data 屬性并將這個(gè) prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
- 這個(gè) prop 以一種原始的值傳入且需要進(jìn)行轉(zhuǎn)換。在這種情況下,最好使用這個(gè) prop 的值來(lái)定義一個(gè)計(jì)算屬性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
v-model
首先我們要知道v-model指令是用來(lái)在表單 <input>、<textarea> 及 <select> 元素上創(chuàng)建雙向數(shù)據(jù)綁定,但 v-model 本質(zhì)上不過(guò)是語(yǔ)法糖:value="msg" @input="msg = $event.target.value"
注意點(diǎn):v-model 會(huì)忽略所有表單元素的 value、checked、selected attribute 的初始值而總是將 Vue 實(shí)例的數(shù)據(jù)作為數(shù)據(jù)來(lái)源。你應(yīng)該通過(guò) JavaScript 在組件的 data 選項(xiàng)中聲明初始值。

實(shí)現(xiàn)組件Props雙向綁定
在Vue2中組件的props的數(shù)據(jù)流動(dòng)改為了只能單向流動(dòng),即只能由組件外(調(diào)用組件方)通過(guò)組件的DOM屬性attribute傳遞props給組件內(nèi),組件內(nèi)只能被動(dòng)接收組件外傳遞過(guò)來(lái)的數(shù)據(jù),并且在組件內(nèi),不能修改由外層傳來(lái)的props數(shù)據(jù)。
假如我現(xiàn)在需要做一個(gè)彈出層組件,需求:
- 通過(guò)點(diǎn)擊按鈕實(shí)現(xiàn)彈出(顯示)
- 不點(diǎn)擊按鈕,點(diǎn)擊自己隱藏,或者直接修改狀態(tài)實(shí)現(xiàn)隱藏和顯示
方案一:
由于子組件不能直接修改props的值,所以:
- 子組件內(nèi)的data下創(chuàng)建一個(gè)Props屬性的副本
- 監(jiān)聽(tīng)props屬性 賦予data副本 來(lái)同步組件外對(duì)props的修改
- 創(chuàng)建針對(duì)props副本的watch,通知到組件外
解釋:在第2步驟之后,我們?cè)诮M件內(nèi)修改了props的副本testShow,組件外此時(shí)不知道組件內(nèi)的props狀態(tài),所以需要再創(chuàng)建一個(gè)針對(duì)props副本testShow的監(jiān)聽(tīng),即對(duì)應(yīng)data屬性的watch

缺點(diǎn):
父組件必須有個(gè) showChange 這樣的方法,有點(diǎn)累贅。
思考:
個(gè)人認(rèn)為只有在滿足以下條件時(shí)再使用雙向綁定的props:
- 組件內(nèi)部需要修改props。
- 組件需要可以由外部在運(yùn)行時(shí)動(dòng)態(tài)控制,而非單純初始化。
- 組件外部需要讀取組件內(nèi)的狀態(tài)來(lái)進(jìn)行處理
滿足上述條件的有比如switch開(kāi)關(guān)組件,需要外部控制開(kāi)關(guān)狀態(tài);再比如Tab多標(biāo)簽頁(yè)組件的activeIndex屬性,需要可以由外部控制標(biāo)簽頁(yè)當(dāng)前打開(kāi)哪一頁(yè)等等
方案二:
v-model指令是用來(lái)在表單
<input>、<textarea> 及 <select>元素上創(chuàng)建雙向數(shù)據(jù)綁定,但 v-model 本質(zhì)上不過(guò)是語(yǔ)法糖:value="msg" @input="msg = $event.target.value"

這種實(shí)現(xiàn)父子組件見(jiàn)v-model綁定值的方法,在我們開(kāi)發(fā)中其實(shí)是很常用的,特別是你要封裝公共組件的時(shí)候。
方案三
先看下官方文檔:vue .sync修飾符,里面說(shuō)vue .sync 修飾符以前存在于vue1.0版本里,但是在在 2.0 中移除了 .sync 。但是在 2.0 發(fā)布之后的實(shí)際應(yīng)用中,我們發(fā)現(xiàn) .sync還是有其適用之處,比如在開(kāi)發(fā)可復(fù)用的組件庫(kù)時(shí)。我們需要做的只是讓子組件改變父組件狀態(tài)的代碼更容易被區(qū)分。從 2.3.0 起我們重新引入了 .sync修飾符,但是這次它只是作為一個(gè)編譯時(shí)的語(yǔ)法糖存在。它會(huì)被擴(kuò)展為一個(gè)自動(dòng)更新父組件屬性的 v-on 監(jiān)聽(tīng)器。 .sync屬性 使用方法跟 v-model 類似
vue 修飾符sync的功能是:當(dāng)一個(gè)子組件改變了一個(gè) prop 的值時(shí),這個(gè)變化也會(huì)同步到父組件中所綁定。如果我們不用.sync,我們想做上面的那個(gè)彈窗功能,我們也可以props傳初始值,然后事件監(jiān)聽(tīng),實(shí)現(xiàn)起來(lái)也不算復(fù)雜。這里用sync實(shí)現(xiàn),只是給大家提供一個(gè)思路,讓其明白他的實(shí)現(xiàn)原理,可能有其它復(fù)雜的功能適用sync。
<comp :foo.sync="bar"></comp>
會(huì)被擴(kuò)展為:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
當(dāng)子組件需要更新 foo 的值時(shí),它需要顯式地觸發(fā)一個(gè)更新事件:
this.$emit('update:foo', newValue)
