自定義組件v-model的實質性理解

用了幾個月Vue一直很糾結自定義組件的v-model實現,最近開始學習React時,React中受控組件與狀態提升的理念與v-model不謀而合。

自定義組件v-model的實質性理解

在Vue與React中其實都存在單向數據流的概念,只不過Vue中通過各種語法糖被弱化了,比如React與Vue中的props都是單向傳輸數據的。在React中如果想實現類似於v-model的功能,需要這樣實現:

父組件:

class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'};
}
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (

scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
celsius={parseFloat(celsius)} />

);
}
}

子組件:

class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (

Enter temperature in {scaleNames[scale]}:
onChange={this.handleChange} />

);
}
}

這是一個輸入水溫從而監控水是否沸騰的一個小組件。子組件是一個溫度輸入的input控件,父組件是由兩個溫度輸入(華氏與攝氏)與一個現實水是否沸騰的指示器組成。父組件存在一個state作為唯一數據源用於存放溫度等值於狀態,溫度通過子組件的prop傳入子組件內部通過input的value屬性顯示在基礎輸入框中,當在基礎輸入框中觸發輸入時間時,onChange事件觸發由prop傳入的onTempreture事件並附帶變化後的值,再由父組件的handleCelsiusChange/handleFahrenheitChange事件處理方法將基礎輸入框傳來的值寫入state中,再由state通過prop將溫度傳入子組件完成一次數據的更新。這其中其實已經完成了對Vue中

基礎組件v-model的理解與自定義組件v-model的理解。

轉載請註明地址: https://www.cnblogs.com/sonoda-umi/p/9750188.html

在Vue官方文檔中,對原生組件v-model的解釋是這樣的:

 v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>

v-model其實是上面寫法的語法糖。其實就是將this.searchText的值通過名為value的prop傳入input組件內,而後當input事件觸發時將事件帶來的input的新值寫入this.searchText中,然後根據this.searchText中值的變化通過value的prop傳入input控件完成input控件上值的變化,如果去掉v-on...後,這個控件將變為一個只讀控件。

對於自定義組件,文檔中有這樣的解釋:

一個組件上的 v-model 默認會利用名為 value 的 prop 和名為 input 的事件,但是像單選框、複選框等類型的輸入控件可能會將 value 特性用於不同的目的。model 選項可以用來避免這樣的衝突:


Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {

checked: Boolean
},
template: `
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
現在在這個組件上使用 v-model 的時候:

這裡的 lovingVue 的值將會傳入這個名為 checked 的 prop。同時當 觸發一個 change 事件並附帶一個新的值的時候,這個 lovingVue 的屬性將會被更新。

其實就是將原來v-model默認使用的名為value的prop與名為input的event自定義一個名字使用,在上面自定義組件中存在

props: {
checked: Boolean
}

說明checked本質上還是一個prop,然後在子組件的model屬性中將自定義的prop與event註冊,而觸發model中event時也就是通過觸發子組件的事件在父組件中修改綁定自定義prop的變量的值的過程,這樣這個過程就很明顯了:

1.父組件創建一個名為tmp變量綁定名為checked的prop的值(已被修飾為v-model)並根據父組件中tmp值的變化將變化後的值傳入子組件中,引起子組件checkbox狀態變化;

2.子組件中checkbox被勾選,觸發checkbox的change事件,通過this.$emit方法觸發子組件的change事件並將change事件產生的新值傳入;

3.因為在model屬性中已將v-model語法糖中event註冊為change(換成其他名字也都可以),v-model會自動將子組件傳來的值傳入tmp變量中;

4.Vue監聽到tmp值的變化,執行第一步,更新子組件中checkbox的狀態;

其實上面的子組件可以換個寫法更容易理解:

Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'test'
},
props: {
checked: Boolean
},
template: `
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('test', $event.target.checked)"
>
`
})

父組件中調用時可以這樣寫:


這樣對v-model的理解也就一目瞭然了。

轉載: https://www.cnblogs.com/sonoda-umi/p/9750188.html

這些技術如何學習,有沒有免費資料?

對前端的技術,架構技術感興趣的同學關注我的頭條號,並在後臺私信發送關鍵字:“前端”即可獲取免費的架構師學習資料

知識體系已整理好,歡迎免費領取。還有面試視頻分享可以免費獲取。關注我,可以獲得沒有的架構經驗哦!!


分享到:


相關文章: