一.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的理解,如有不对的地方,请在下方纠正。