踩坑 v-model。
问题描述
在Vue项目中,使用flatpickr 做一个日期选择器DatePicker的组件,发现使用v-model时出了问题。
上图:
这里当我更新新的日期时,v-model并没有同步更新,而是保持着初始值。
对应的HTML及组件定义的代码如下:
HTML:
<template>
<div>
<div class="form-group row">
<label class="col-form-label text-right col-4">昵称</label>
<div class="col">
<input v-model="nickname" name="nickname" type="text" class="form-control">
</div>
</div>
{{ nickname }}
<div class="form-group row">
<label class="col-form-label text-right col-4">生日</label>
<div class="col">
<DatePicker v-model="birthday" name="birthday">
</div>
</div>
{{ birthday }}
</div>
</template>
<script>
export default {
data() {
return {
nickname: 'lucia',
birthday: '2018-12-26'
}
}
}
</script>
DatePicker组件的内容:
<template>
<div class="input-group flatpickr" data-alt-input="true" data-locale="zh" data-alt-format="Y-m-d">
<input :value="value" :name="name" class="flatpickr-input" data-input="true">
<a class="input-group-append" data-toggle>
<span class="input-group-text">
<i class="far fa-calendar-alt" />
</span>
</a>
</div>
</template>
<script>
import initFlatpickr from './flatpickr'
export default {
props: [ "value", "name" ],
mounted() {
initFlatpickr(this.$el)
}
}
</script>
「其中initFlatpickr用于创建flatpickr实例,这里它不是重点,具体内容略去。」
Google后,参考Adding v-model Support to Custom Vue.js Components,完美解决。
解决方法
解决问题前,需要了解,v-model 是语法糖,以下两种写法得到的效果是一样的:
<input v-model="message" type="text">
<input :value="message" @input="message = $event.target.value" type="text">
而对于组件DatePicker,我只需要在发生input事件时,将值传给父组件的input事件即可。
接下来就自然而然了。
修改DatePicker组件的input部分内容,监听input事件,当发生input事件后调用updateDate()方法,emit父组件的input事件,将用户选中的值传给父组件。
这里只显示修改部分的代码:
<template>
......
<input :value="value" :name="name" class="flatpickr-input" data-input="true" @input="update" ref="datePicker" @input="updateDate">
......
</template>
<script>
.......
export default {
.......
methods: {
updateDate() {
this.$emit('input', this.$refs.datePicker.value)
}
}
}
</script>
这时再看刚刚的页面,问题解决。