我需要在不同的组件中使用Vuetify v-date-picker
。但这将导致代码重复。因此,我认为创建一个自定义<custom-date-picker />
组件可以在任何需要的地方使用会很有趣。
但是使用我当前的代码,我收到以下错误消息:
[Vue warn]: Avoid 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"
found in
---> <CustomDatePicker> at components/CustomDatePicker.vue
<Pages/index.vue> at pages/index.vue
父组件是pages / index.vue :
<template>
<div>
<custom-date-picker v-model="date" />
<v-btn @click="getDate">
Ok
</v-btn>
</div>
</template>
<script>
import CustomDatePicker from '@/components/CustomDatePicker.vue'
export default {
components: { CustomDatePicker },
data () {
return {
date: ''
}
},
methods: {
getDate () {
console.log(this.date)
}
}
}
</script>
子组件是components / CustomDatePicker.vue :
<template>
<v-container fill-height>
<v-row justify="center" align="center">
<v-col cols="12">
<!-- Date picker -->
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="false"
transition="scale-transition"
offset-y
>
<template v-slot:activator="{ on }">
<v-text-field
v-bind:value="value"
v-on:input="$emit('input', $event)"
@blur="date = parseDate(value)"
v-on="on"
value
label="Date"
color="green lighten-1"
/>
</template>
<v-date-picker
v-model="date"
@input="menu1 = false"
no-title
header-color="green lighten-1"
color="green lighten-1"
/>
</v-menu>
<!-- end of date picker -->
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'CustomDatePicker',
props: {
value: {
type: String,
default: ''
}
},
data () {
return {
menu1: null,
date: null
}
},
computed: {
computedDateFormatted () {
return this.formatDate(this.date)
}
},
watch: {
date (val) {
this.value = this.formatDate(this.date)
}
},
methods: {
formatDate (date) {
if (!date) { return null }
return date
},
parseDate (date) {
if (!date) { return null }
const [year, month, day] = date.split('-')
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
}
}
}
</script>
如何解决我的问题?
如果有时间,可以在Github上使用此simple demo:)
更新1:
通过避免对prop value
进行变异,我成功摆脱了上面的错误消息。我可以选择日期,然后单击确定按钮,可以正确记录日期控制台。
问题在于父组件的文本字段未显示我选择的日期,而是保留了上图中显示的日期。
这是子组件的更新代码:
<template>
<v-container fill-height>
<v-row justify="center" align="center">
<v-col cols="12">
<!-- Date picker -->
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="false"
transition="scale-transition"
offset-y
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="dateFormatted"
@blur="date = parseDate(dateFormatted)"
v-on="on"
value
label="Date"
color="green lighten-1"
/>
</template>
<v-date-picker
v-bind:value="value"
v-on:input="$emit('input', $event)"
@input="menu1 = false"
no-title
header-color="green lighten-1"
color="green lighten-1"
/>
</v-menu>
<!-- end of date picker -->
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'CustomDatePicker',
props: {
value: {
type: String,
default: ''
}
},
data () {
return {
menu1: null,
date: null,
dateFormatted: null
}
},
computed: {
computedDateFormatted () {
return this.formatDate(this.date)
}
},
watch: {
date (val) {
this.dateFormatted = this.formatDate(this.date)
}
},
methods: {
formatDate (date) {
if (!date) { return null }
return date
},
parseDate (date) {
if (!date) { return null }
const [year, month, day] = date.split('-')
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
}
}
}
</script>
答案 0 :(得分:1)
为了使它起作用而进行的更改是,我添加了computed
和get()
和set()
。吸气剂将返回当前选择的值,而每次更改时,setter都会发出新值。
这是在自定义组件中利用v-model
的好方法。
CustomDatePicker.vue
<template>
<v-container fill-height>
<v-row justify="center" align="center">
<v-col cols="12">
<!-- Date picker -->
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="false"
transition="scale-transition"
offset-y
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="selected"
v-on:input="$emit('input', $event)"
@blur="date = parseDate(value)"
v-on="on"
value
label="Date"
color="green lighten-1"
/>
</template>
<v-date-picker
v-model="selected"
@input="menu1 = false"
no-title
header-color="green lighten-1"
color="green lighten-1"
/>
</v-menu>
<!-- end of date picker -->
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'CustomDatePicker',
props: {
value: {
type: String,
default: ''
}
},
data () {
return {
menu1: null,
date: null
}
},
computed: {
selected: {
get() {
return this.value
},
set(value) {
this.$emit('input', value)
}
},
computedDateFormatted () {
return this.formatDate(this.date)
}
},
watch: {
date (val) {
this.value = this.formatDate(this.date)
}
},
methods: {
formatDate (date) {
if (!date) { return null }
return date
},
parseDate (date) {
if (!date) { return null }
const [year, month, day] = date.split('-')
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
}
}
}
</script>