v-model实现双向绑定自定义组件
默认v-model去除语法糖
关于组件封装,可以参考我的另外两篇文章《sync修饰符做双向绑定》和《使用watch实现组件props双向绑定》
默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event(就是this.$emit(‘input’,...)向外发送的事件)。比如:
<child v-model="imgs">
// 等价于
<child :value="imgs"
@input="val => { foo = val }"
>
data() {
return {
imgs: [....]
}
}
使用v-model实现父子组件双向数据绑定
// 父组件 urls=[...图片链接的数组]
<div v-for="(item, index) in urls">
<child v-model="item.url">
</div>
<div class="upload-x"
@drop="faceDrop($event)"
>
<!-- 可以不带input <input type="hidden" v-model="_value"> -->
<img :src="_value">
<span v-show="_value" @click="deleteImg">删除</span>
</div>
export default {
props: {
// 默认情况,v-model 会把 value 用作 prop
value: {
type: String,
default() {
return '';
}
}
},
// 直接v-model绑定报错,子组件中不能直接修改父组件传的prop
// 使用computed计算属性重新赋值:
computed: {
_value: {
get() {
return this.value;
},
set(val) {
// 默认情况,把input 用作 向外发送的event事件名称
this.$emit('input', val);
}
}
},
methods: {
// 删除图片
deleteImg(){
this._value = '';
},
// 使用拖拽给_value进行赋值
faceDrop(event) {
let imgUrl = event.dataTransfer.getData('URL');
this._value = imgUrl;
}
...
},
}
使用model属性自定义
使用watch监听属性变化向外发送事件
<child v-model="item.url"></child>
// child中
<div class="upload-x"
@drop="faceDrop($event)"
>
<img :src="myImg">
<span v-show="myImg" @click="deleteImg">删除</span>
</div>
model: {
// v-model传递进来的值
prop: "imgUrl",
// 这里的事件名称需要与下面watch中的发送的事件名称相同,默认是Input
event: "changeImg"
},
props: {
imgUrl: {
type: String,
required: ''
}
},
data() {
return {
// 使用data实现本地组件接收props传递过来的值
myImg: this.imgUrl
}
},
methods: {
deleteImg(){
this.myImg = '';
},
// 拖拽在输入框上释放鼠标
faceDrop(event) {
let imgUrl = event.dataTransfer.getData('URL');
this.myImg = imgUrl;
}
},
watch: {
// 监听值的变化,向外发送事件
myImg(newval) {
// 需要与上面model中事件名称相同
this.$emit('changeImg', newval);
}
}
使用计算属性代替watch(推荐)
<child v-model="item.url"></child>
// child中
<div class="upload-x"
@drop="faceDrop($event)"
>
<img :src="myImg">
<span v-show="myImg" @click="deleteImg">删除</span>
</div>
model: {
// v-model传递进来的值
prop: "imgUrl",
// 这里的事件名称需要与下面watch中的发送的事件名称相同,默认是Input
event: "changeImg"
},
props: {
imgUrl: {
type: String,
required: ''
}
},
computed: {
// 使用计算属性代替watch
myImg: {
get() {
return this.imgUrl;
},
set(val) {
// 这里发送的事件名称需要与上面Model中的一致!
this.$emit('changeImg', val);
}
}
},
methods: {
deleteImg(){
this.myImg = '';
},
// 拖拽在输入框上释放鼠标
faceDrop(event) {
let imgUrl = event.dataTransfer.getData('URL');
this.myImg = imgUrl;
}
}