如何在vue3中优雅地使⽤v-model?
⽂章⽬录静止状态下车被水泡了
ps:vue3中推荐使⽤的是reactive写法,⽂中这种格式只是为了和vue2做对照,只是为了凸显vue3中对v-model的改进,仅供参考。
Vue中的数据绑定
绑定数据有三种⽅式:
插值,也就是{{name}}的形式,以⽂本的形式和实例data中对应的属性进⾏绑定
v-bind
v-model
v-bind
eg:v-bind:class 可简写为 :class
当加上v-bind:之后,它的值classe不是字符串,⽽是vue实例对应的data.class的这个变量。也就是说data.class是什么值,它就会给class属性传递什么值,当data.class发⽣变化的时候,class属性也发⽣变化,这⾮常适合⽤在通过css来实现动画效果的场合。他只是单向变动
太佳高速
v-bind⽀持的类型
html中的属性、css的样式、对象、数组、number 类型、bool类型
v-bind使⽤
// 绑定⽂本
<p v-bind="message"></p>
// 绑定属性
<p src="...."></p>
<p class="...."></p>
<p ></p>
// 绑定表达式
:class{className:true}
v-model
a8论坛
v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型⾃动选取正确的⽅法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听⽤户的输⼊事件以更新数据,并对⼀些极端场景进⾏⼀些特殊处理
主要是⽤在表单元素中,它实现了双向绑定。在同时使⽤v-bind和v-model中,v-model建⽴的双向绑定对输⼊型元素input, textarea, select等具有优先权,会强制实⾏双向绑定。很多时候v-model使⽤在表单的<input>中实现双向绑定。
v-model实现了表单输⼊的双向绑定,⼀般是这么写的:
<input v-model="price">
</div>
<script>
new Vue({
el:'#app',
data:{
price:''
}
});
</script>
通过该语句实现price变量与输⼊值双向绑定
实际上v-model只是⼀个语法糖,真正的实现是这样的:
<input type="text"
      :value="price"
      @input="price=$event.target.value">
以上代码分⼏个步骤:
进口现代圣达菲将输⼊框的值绑定到price变量上,这个是单向绑定,意味着改变price变量的值可以改变input的value,但是改变value不能改变price 监听input事件(input输⼊框都有该事件,当输⼊内容时⾃动触发该事件),当输⼊框输⼊内容就单向改变price的值
这样就实现了双向绑定。
<input v-model="giveDate"/>
<input :value="giveDate"@input="giveDate = $event.target.value"/>
第⼀⾏的代码其实只是第⼆⾏的语法糖。
vue2中v-model⽤法
不使⽤v-model的双向绑定
如下代码所⽰,这是不⽤v-model时候的写法。
组件使⽤v-bind给⼦组件中的props传值。
⼦组件需要使⽤emit⽅法来实现⼦组件---->⽗组件⽅向上的绑定。
⽗组件
<div>
<!--在⼦组件中⽤emit("test")传达给⽗组件的getData⽅法中-->熊猫轿车
<search @test="getData":keywords="keywords"></search>
<button @click="submit">提交</button>
</div>
</template>
<script>
import search from'@/components/index/search.vue'
export default{
data(){
return{
keywords:''
}
},
components:{
search
},
methods:{
/
/ 在这⾥实现更改⽗组件的值
getData(val){
this.keywords = val
},
submit(){
console.log('keywords:',this.keywords)
}
}
}
</script>
⼦组件
<!--⼦组件-->
<template>
<div>
<input @input="inputChange"type="text"name="keywords">
</div>
</template>
<script>
export default{
props:['keywords'],
methods:{
inputChange(e){
/
/ 传给⽗元素的test函数
this.$emit('test', e.target.value)
}
}
}
</script>
即,在⽗组件中,通过v-bind给⼦组件传参,同时指定v-on和指定修改⽬标值的函数。开一个洗车店要多少钱
在⼦组件中,接受⽗组件v-bind传过来的值,实现⽗->⼦⽅向上的绑定,然后通过emit⽅法,向⽗组件传出$event.target.value,实现⼦->⽗⽅向上的绑定。
使⽤v-model后
⽗组件
<div class="parent"><p>⽗组件将传递给⼦组件的数据是:
<input type="text"v-model="giveChildData"/></p>
<Child v-model="giveChildData"></Child>
</div>
</template>
<script>
import Child from'./Child.vue';
export default{
name:"Father",
data(){
return{
todosth:0,
giveChildData:'⼉⼦,爸要把家产传给你啊!'
};
},
components:{
Child
}
}
</script>
⼦组件
<!-- child -->
<template>
<div class="child">
<p>⼦组件将通过$emit调⽤⽗组件的函数并修改数据:{{ give }}</p>
<span @mousemove="returnBackFn">答复</span>
</div>
</template>
<script>
export default{
name:"Child",
props:{
give:
{
type: String,
default:'0'
}
},
model:{
prop:'give',
event:'returnBack'
},
methods:{
returnBackFn(){
this.$emit('returnBack','啥家产?有矿啊!');
}
}
};</script>
这⾥的 giveChildData 的值将会传⼊这个名为 give 的 prop。同时当 <Child>触发⼀个 returnBack 事件并附带⼀个新的值的时候,这个giveChildData 的属性将会被更新。
问题
但是当有多个数据需要⽗⼦组件之间双向绑定时,v-model只能传其中⼀个值。这时候需要使⽤.sync来实现其他数据的绑定。
.sync
从 2.3.0 起,vue重新引⼊了 .sync 修饰符,但是这次它只是作为⼀个编译时的语法糖存在。它会被扩展为⼀个⾃动更新⽗组件属性的 v-on 。
⽰例代码如下:
<comp :foo.sync="bar"></comp>
<comp :foo="bar"@update:foo="val => bar = val"></comp>
当⼦组件需要更新 foo 的值时,它需要显式地触发⼀个更新事件:
this.$emit('update:foo', newValue)
实例如下。(弹窗的关闭事件)
<template>
<div class="details">
<myComponent
:show.sync='valueChild'
>
</myComponent>
<button @click="changeValue">toggle</button>
</div>
</template>
<script>
import Vue from'vue'
Vueponent(
'myComponent',{
template:`
<div v-if="show">
<p>默认初始值是{{ show }},所以是显⽰的</p>
<button @click.stop="closeDiv">关闭</button>
</div>`,
props:['show'],
methods:{
closeDiv(){
this.$emit('update:show',false);//触发 input 事件,并传⼊新值
}
}
})
export default{
data(){
return{
valueChild:true,
}
},
methods:{
changeValue(){
this.valueChild =!this.valueChild
}
}
}
</script>
效果如下图。
vue2中使⽤v-model + .sync
由于v-model只能默认传进去⼀个值,剩下的需要使⽤.sync实现双向绑定。