在vue中,v-model是用来进行数据双向绑定的一个语法糖,比如说用在input上,输入框数据变化,v-model绑定的对应的值也会跟着变化,无需单独获取。
其实v-model还可以在自定义组件中使用,可以被拆解为props:value和event:input,也就是说组件必须接收一个value值以及名为input的自定义事件,就可以在自定义组件上使用v-model了。
新建一个组件Input.vue
<template>
<div class="input">
<button @click="changeNum(-1)">-</button>
<span>{{currentVal}}</span>
<button @click="changeNum(1)">+</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
}},
data() {
return {
currentVal: this.value
};
},
watch: {
value(val) {
this.currentVal = val;
}
},
methods: {
changeNum(val) {
this.currentVal += val;
this.$emit('input',this.currentVal);
}
}
};
</script>
<style>
.input{
display: flex;
}
</style>
在使用组件时:
<template>
<div class="wrap">
<input-model v-model="valueInput"></input-model>
</div>
</template>
<script>
import InputModel from "./Input";
export default {
components: {
InputModel
},
data() {
return {
valueInput: 1
};
},
watch: {
valueInput(val) {
console.log(val) // 在这里可以监听到值的变化
}
},
methods: {
changeArr
}
};
</script>
<style>
</style>
可以看到,用了v-model后,无需在组件上显示的声明@input事件去监听、改变组件内部的数据变化,同样实现了数据的双向绑定。
这种一般会用在组件内部想要修改props传入的值的时候,因为组件内部是不允许直接修改props值,类似于这样的修改是会抛出错误的:
<template>
<div class="input">
<button @click="changeNum(-1)">-</button>
<span>{{value}}</span>
<button @click="changeNum(1)">+</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
}},
data() {
return {
};
},
methods: {
changeNum(val) {
this.value += val; // 抛出错误
}
}
};
</script>
<style>
.input{
display: flex;
}
</style>
意思就是不能直接修改
还可以用computed计算属性接收一下这个数据,重新赋值,然后就可以修改了
平时我们用得比较多的都只是这样的:
<template>
<div class="input">
<span>{{currentVal}}</span>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
}},
data() {
return {
};
},
computed: {
currentVal() {
return this.value
}
},
methods: {
}
};
</script>
<style>
.input{
display: flex;
}
</style>
直接使用就行,但是要利用computed进行修改就还需要加上computed的另一个属性set,上面默认是使用了get函数,即:
computed: {
currentVal: {
get() {
return this.value
}
}
}
加上set方法后就可以对其进行设置,并向上触发input事件:
<template>
<div class="input">
<button @click="changeNum(-1)">-</button>
<span>{{currentVal}}</span>
<button @click="changeNum(1)">+</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
}},
data() {
return {
};
},
computed: {
currentVal: {
get() {
return this.value
},
set(val) {
this.$emit("input",val);
}
}
},
methods: {
changeNum(val) {
this.currentVal += val;
}
}
};
</script>
<style>
.input{
display: flex;
}
</style>