这次想说一下自定义组件的赋值问题。
为了在画面中使用日期选择,导入了vue-calendar,示例代码如下:
<v-date-picker v-model="dateValue">
<template v-slot="{ inputValue, inputEvents }">
<input class="bg-white border px-2 py-1 rounded"
:value="inputValue" v-on="inputEvents"
/>
</template>
</v-date-picker>
因为需要使用的地方有多处,所以打算把它做成一个自定义组件。
<template>
<v-date-picker v-model="dateValue">
<template v-slot="{ inputValue, inputEvents }">
<input class="bg-white border px-2 py-1 rounded"
:value="inputValue" v-on="inputEvents"
/>
</template>
</v-date-picker>
</template>
<script>
export default {
props: {
value: Date
},
data() {
return {
dateValue: this.value
}
}
}
</script>
然后,在view界面就可以通过下面的方式使用了:
<calendar v-model="date"></calendar>
这里说一下,component 里面,为什么要把value和dateValue分开,因为给component赋值的时候,只能通过props进行赋值。如果赋值完需要更新的话,就必须使用data或者compute进行绑定。不然的话,就会爆出下面的错误:
mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
上面的组件的写法,可以实现父到子之间的赋值传递,但是子组件里的值改变的时候,不会跟父组件进行联动。为了实现子组件到组件的赋值联动,还需要加上下面这么一段:
watch: {
dateValue: function(val) {
console.log('value changed:' + val)
this.$emit('input', val)
}
}
子组件的值改变的时候,通过watch检测出来,然后执行 this.$emit(‘input’, val), 这段代码需要解释一下,下面两种方式作用其实是相同的。
<calendar v-model="date"></calendar>
<calendar v-bind:value="date" v-on:input="data = $event.target.value"></calendar>
// By default, v-model on a component uses value as the prop and input as the event (from VueJs Official Document)
在子组件执行 this.$emit(‘input’, val) ,其实是触发了父组件的input event。这样就可以把值传递会去了。
所以,总结一下就是,父→子之间通过props进行传值,然后子→父通过$emit进行传值。
最后,完整的示例代码如下:
<template>
<v-date-picker v-model="dateValue">
<template v-slot="{ inputValue, inputEvents }">
<input class="bg-white border px-2 py-1 rounded"
:value="inputValue" v-on="inputEvents"
/>
</template>
</v-date-picker>
</template>
<script>
export default {
props: {
value: Date
},
data() {
return {
dateValue: this.value
}
},
watch: {
dateValue: function(val) {
console.log('value changed:' + val)
this.$emit('input', val)
}
}
}
</script>
参考文章:
https://jp.vuejs.org/v2/guide/components-custom-events.html
https://vcalendar.io/datepicker.html
https://recruit.cct-inc.co.jp/tecblog/vue-js/vue-emit-props/