一.v-model是如何工作的
input, select, textarea等是我們常用的在應用中傳遞數據的途徑。在vue中我們可以通過v-model進行雙向數據綁定,下面看一個例子:
<div id="app1">
<input type="text" v-model="message">
<span>{{message}}</span>
</div>
<script>
var app1 = new Vue({
el:'#app1',
data:{
message:"Hello Vue"
}
});
</script>
打開瀏覽器,查看渲染結果。
更改文本內容,可以看到中的內容會跟隨變化。
其實vue在解釋v-model的時候會做一個轉化工作,實質是下面這樣:
<div id="app2">
<input type="text" :value="message" @input="message = $event.target.value">
<span>{{message}}</span>
</div>
<script>
var app2 = new Vue({
el:'#app2',
data:{
message:"Hello Vue"
}
});
</script>
通過input元素的value屬性,和input事件達到v-model的作用。
二.仿照v-model的實現方法,在自定義組件上實現v-model功能
瞭解了v-model的本質,我們可以在自定義組件上模擬v-model的功能。編輯代碼如下:
<div id="app3">
<custom-input2 :inputValue="message" @input-change="message=$event.target.value" :value="message"></custom-input2>
<span>{{message}}</span>
</div>
<script type="text/javascript">
Vue.component('custom-input2', {
props:{
inputValue:String
},
template:`<input type="text" :value="inputValue" @input="$emit('input-change', $event)"/>`
});
var app3 = new Vue({
el:'#app3',
data:{
message:'Hello Vue'
}
});
</script>
打開瀏覽器,查看渲染結果,並修改文本框中的值,可以看到我們的目的達到了:
但是這樣做法有點太麻煩,能不能利用v-model達到我們想要的結果呢,請繼續往下面看。
三.自定義組件應用v-model
先直接在自定義組件上使用v-model:
<div id="app4">
<custom-input v-model="message"></custom-input>
<span>{{message}}</span>
</div>
<script>
Vue.component('custom-input3',{
props:{
value:String
},
});
var app3 = new Vue({
el:'#app3',
data:{
message:'Hello Vue'
}
});
</script>
當然這肯定無法達到我們想要的結果,那應該怎麼實現呢,首先,要明確的是v-model接受一個value屬性和一個input屬性,先看下面一個例子:
<div id="app">
<basic-input :value="name" @input="name=$event"></basic-input>
<p>
<strong>Name:</strong> {{ name }}
</p>
</div>
<script type="text/javascript">
const BasicInput = {
template: '<input v-model="content" @input="handleInput" />',
prop: ['value'],
data() {
return {
content: this.value
}
},
methods: {
handleInput(e) {
this.$emit('input', this.content)
}
}
}
new Vue({
el: '#app',
data: { name: '' },
components: { BasicInput }
})
</script>
渲染結果:
上面代碼功能是我們想要的,但是basic-input還是沒有用到v-model,但是我們可以發現,它用到了value屬性和input事件,那麼我們只需要在使用組件的地方更改成如下代碼就可以了:
<basic-input v-model="name"></basic-input>
好,至此我們已經實現了在自定義組件上使用v-model的目的,但真的結束了嗎?通過上面的研究可以發現,v-model最終轉化爲value屬性和input事件來實現,這就限制了使用的範圍,怎麼使用我們自定義的事件和屬性呢,請繼續往下看。
四.使用自定義事件和屬性
vue組件爲我們提供了一個model屬性,這個屬性可以幫助我們達到使用自定義事件和屬性的目的,將代碼修改如下:
<div id="app">
<basic-input v-model="name"></basic-input>
<p>
<strong>Name:</strong> {{ name }}
</p>
</div>
<script type="text/javascript">
const BasicInput = {
template: '<input v-model="content" @input="handleInput" />',
prop: ['new-value'],
model:{
event:'input-change',
prop:'new-value'
},
data() {
return {
content: this.new-value
}
},
methods: {
handleInput(e) {
this.$emit('input-change', this.content)
}
}
}
new Vue({
el: '#app',
data: { name: '' },
components: { BasicInput }
})
</script>
vue在解析 <basic-input v-model="name"></basic-input>
時,會將其轉化爲<basic-input :new-value=name @input-change="name=$event"></basic-input>
.
以上就是我對v-model的理解,如有不對的地方,請在下方糾正。