I have very common problem with upgrading to Vue 2.0
I am getting warning:
Avoid mutating a prop directly since the value will be overwritte
You should make a computed property with a getter and setter and then use $emit
to update the property, e.g:
var GuestMenu = Vue.extend({
props: ['username', 'password'],
template: `
<div id="auth">
<form class="form-inline pull-right">
<div class="form-group">
<label class="sr-only" for="UserName">User name</label>
<input type="username" v-model="usernameInput" class="form-control" id="UserName" placeholder="username">
</div>
<div class="form-group">
<label class="sr-only" for="Password">Password</label>
<input type="password" v-model="passwordInput" class="form-control" id="Password" placeholder="Password">
</div>
</form>
</div>`,
computed: {
usernameInput: {
get: function(){
return this.username;
},
set: function(newValue){
this.$emit('update:username', newValue)
}
},
passwordInput: {
get: function(){
return this.password;
},
set: function(newValue){
this.$emit('update:password', newValue)
}
},
}
});
Vue.js consider this as anti-pattern. For example, declaring and setting some props like
this.propsVal = 'new Props Value'
So to solve this issue you have to take in value from the props to data or computed property of Vue instance. like...
props: ['propsVal'],
data: function() {
return {
propVal: this.propsVal
};
},
methods: {
...
}
and you can use your props value like normally.
if you want to mutate props - use object.
<component :user="global.user"></component>
component:
props: ['user'],
methods: {
setUser: function() {
this.user.username= "User";
this.user.password= "myPass123";
}
}
When you use v-bind
the property is bind using two directions, that is why you get the warning.
If you need to pass the initial username from the parent Vue component, you can use v-bind
with another data property such as _username
and copy the initial value from the property to the internal data when the component is created:
props : ['username', 'password'],
data () {
return {
_username: this.username,
_password: this.password
}
}
Edit: you can also use a $watch to update the _username / _password component data when the properties change.
you can use the emit, then:
<text-document :title.sync="title"></text-document>
to change the value is:
this.$emit('update:title', newTitle)
or another way:
this.$emit('update')
and you can get on the template:
<text-document :update="oneFunctionInMethods()"></text-document>
I'm not sure what exactly you want to achieve but I'll take two options out of it.
First one: It's all about getting rid of this warning.
data () {
return {
childVal: this.parentVal
}
}
Second one: You want to communicate between parent and child.
If I got it right, this is a basic example of an <input>
in a child component communicating with its parent.
Parent HTML:
<p>{{ user }}</p>
<child-component v-model="user">
Parent JS:
data () {
return {
user: 'John'
}
}
Child HTML:
<input v-bind:value="value" @input="$emit('input', $event.target.value)">
Child JS:
props: ['value']
Working example: http://jsfiddle.net/kf3aLr1u/
You can also read more about it in the docs https://vuejs.org/v2/guide/components.html.