v-model
v-model的用法很简单,也就是对输入框等表单组件进行双向绑定,常规用法如下:
<input v-model="value" />
那么,v-model是如何实现这个功能的呢?代码如下:
<input :value="value" @input="value = $event.target.value" />
原理
v-model的实质呢,也是需要通过监听input元素value的变化来实现的,同时也去修改data变量value,input有自己的输入监听事件oninput方法;
那么我们知道了有v-model的两个关键要素:
1、给元素绑定一个value属性;
2、给元素绑定一个oninput方法
那么如果不是input元素,或者我的自定义组件里没有input元素,那么该如何实现呢?
那是不是做到以下两点,我们也能给自己的组件进行v-model了呢?
1、给组件绑定一个value属性;
2、当value需要变化时,给父组件发射一个input事件
自定义组件的v-model
先准备一个子组件Children
<template>
<div class="list">
<div
v-for="(item, index) in list"
:key="index"
:class="[item.checked ? 'active' : '']"
@click="handleTimeChecked(index)"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
name: "Children",
props: {
value: {
type: String,
},
},
data() {
return {
list: [
{ text: "09:00", checked: true },
{ text: "10:00", checked: false },
],
};
},
computed: {},
watch: {
value(val) {
// 监听value变化,及时响应
this.list.forEach((el) => {
if (el.text === val) {
el.checked = true;
} else {
el.checked = false;
}
});
},
},
mounted() {},
methods: {
handleTimeChecked(index) {
// 向父组件发送input事件,修改value值
this.$emit("input", this.list[index].text);
},
},
};
</script>
<style lang="less" scoped>
.list {
display: flex;
> div {
width: 100px;
height: 30px;
line-height: 30px;
margin-right: 10px;
text-align: center;
background: #fff;
color: #000;
cursor: pointer;
&.active {
background: red;
color: #fff;
}
}
}
</style>
然后准备一个父组件Father
<template>
<div >
<Children v-model="value"></Children>
</div>
</template>
<script>
import Children from "Children";
export default {
name: "Father",
components: {
Children ,
},
data() {
return {
value: "",
}
},
};
</script>
<style lang="less" scoped></style>
试了一下效果,还行