Reputation: 3418
I dont understand what is the difference between v-bind
, v-model
and v-bind.sync
?
Maybe it's too late, but I can't tell the difference between v-bind.sync
and v-model
after reading the documentation.
Passing Data to Child Components with Props
I have the following component written in Typescript, using "vue-property-decorator". I don't know how I can manage to update the date
object passed into the component without having to write the event handling myself. If you ask me, it should work with the v-model
and with the v-bind.sync
bindings (and respective changes in the markup and decorator).
<Datepicker v-model="date"/>
import { Component, Prop, Vue, Model } from "vue-property-decorator";
@Component({})
export default class Datepicker extends Vue {
@Prop()
private label!: string;
@Model()
private date!: Date;
private internalDate = new Date().toISOString().substr(0, 10);
private menu = false;
private onDateChanged() {
const isoDate = this.date.toISOString();
const newDate =
this.internalDate + this.date.toISOString().substring(10);
this.date = new Date(newDate);
}
}
Every time I change the this.date
object, I get the warning:
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: "date"
Upvotes: 4
Views: 3640
Reputation: 21030
In Vue.js, you should not mutate the input prop
that is passed to you by the component. For example in your case, consider label
prop. Within your DatePicker
, you should not have any statement that does something like this.label = 'Hello! Change Prop!';
.
TLDR: Do not mutate the prop within your component. Let parent mutate it.
Coming back to your component, you should have a component like this:
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
@Component({})
export default class Datepicker extends Vue {
@Prop()
private label!: string;
@Prop()
private value!: Date;
private internalDate = new Date().toISOString().substr(0, 10);
private previouslyEmittedDate: Date;
private menu = false;
@Watch('value')
public onDatePropChange() {
// Break infinite one-way recursion
if (this.value !== this.previouslyEmittedDate) {
const newDate = new Date(this.internalDate + this.value.toISOString().substring(10));
this.previouslyEmittedDate = newDate;
// input events created a sugar coated v-model binding
this.$emit('input', newDate);
}
}
}
As a side note: I notice some sort of code smell here. On every date change, you are adding some internal date. It will cause infinite one-way binding recursion. v-model
is to be used for input
changed by the user and not programatically. v-model
is just a sugar-coated syntax for the following:
<Datepicker :value="date" @input="this.date = $event"/>
Finally, avoid .sync
modifier. It has a different purpose and should be used sparingly.
Upvotes: 1