Reputation: 4042
I've got a simple Test component, the template looks like this:
<template>
<div>
<input type="text" v-model="name" class="form-control">
<h5>{{ message }}</h5>
</div>
</template>
<script src="./test.ts" lang="ts"></script>
and the component TypeScript looks like this:
declare var Vue: typeof Function;
declare var VueClassComponent: any;
import { Component, Inject, Model, Prop, Watch } from "vue-property-decorator";
@VueClassComponent.default({
template: require("./test.vue"),
style: require("./test.sass"),
props: {
name: String,
num: Number
}
})
export default class TestComponent extends Vue {
name: string;
num: number;
message: string = "";
@Watch("name")
protected onNameChanged(newName: string, oldName: string): any {
console.log("setting " + oldName + " to " + newName);
}
mounted(this: any): void {
console.log("mounted called");
this.message = "Hello " + this.name + " " + this.num;
}
}
When I type in the input
box, the @Watch("name") handler never fires, however I do get these errors in the console
:
[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: "name"
Once for every character entered in the input
box. I have no idea where the name is being set, because I have not set it anywhere. Although that is my goal (to update name) I've been reading you can't just change the value directly, you need to set @Watch handlers, and then somewhere else set them (I still don't understand exactly how but can't even get that for right now.
Upvotes: 6
Views: 8978
Reputation: 687
This was because the name variable is not initialised and so does not yet exist on 'this'. If it was initialised with any value then a proxyGetter would have been created for it and the watch would work.
For Vue 2 this is described here enter link description here
Upvotes: 0
Reputation: 82479
Based on our discussion, the root of the problem here was declaring name
as a property. The intention was that name
was an internal value that would simply be used to derive message
. That being the case, a watch is unnecessary and a computed does the trick.
declare var Vue: typeof Function;
declare var VueClassComponent: any;
import { Component, Inject, Model, Prop, Watch } from "vue-property-decorator";
@VueClassComponent.default({
template: require("./test.vue"),
style: require("./test.sass"),
props: {
num: Number
}
})
export default class TestComponent extends Vue {
name: string;
num: number;
get message(){
return "Hello " + this.name + " " + this.num;
}
}
Upvotes: 3