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.
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;
}
}