I started the https://laracasts.com/series/learning-vue-step-by-step series. I stopped the Vue, Laravel and AJAX classes with the following error:
vue.js:2574 [Vue warn]: Avoid changing props directly as the value will be overwritten whenever the parent component re-renders. Instead, use data or computed properties based on the value of the prop. Changing props: "list" (found in component)
I have this code in main.js
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
I know the problem is in created() when I override the list property, but I'm new to Vue so I have absolutely no idea how to fix it. Does anyone know how (and please explain why) to fix it?
Vue modes are
propsdown,eventsup. Sounds simple, but it's easy to forget when writing custom components.Starting with Vue 2.2.0, you can use v -model (with computed properties). I find this combination creates a simple, clean, and consistent interface between components:
propspassed to the component remains responsive (i.e., it will not be cloned, nor will awatchfunction be required to update the local copy when a change is detected).Computed properties allow setters and getters to be defined individually. This allows the
Taskcomponent to be rewritten as follows:Vue.component('Task', { template: '#task-template', props: ['list'], model: { prop: 'list', event: 'listchange' }, computed: { listLocal: { get: function() { return this.list }, set: function(value) { this.$emit('listchange', value) } } } })Themodel property defines the associated
propandv-model, and which event will be emitted when changed. You can then call this component from the parent component like this:listLocalComputed properties provide a simple getter and setter interface within the component (think of them as private variables). In#task-templateyou can renderlistLocaland it will remain reactive (i.e. ifparentListchanges, it will updateTask component). You can also change thelistLocalby calling a setter (e.g.this.listLocal = newList), which will send the changes to the parent.The advantage of this pattern is that you can pass a
listLocalto a child component ofTask(usingv-model) and make changes from the child component The content will be propagated to the top-level component.For example, suppose we have a separate
EditTaskcomponent that makes some type of modification to task data. By using the samev-modeland computed property pattern, we can passlistLocalto the component (usingv-model):<script type="text/x-template" id="task-template"> <div> <EditTask v-model="listLocal"></EditTask> </div> </script>If the
EditTaskemits a change, it will appropriately callset()on thelistLocal, thereby propagating the event to the top level. Similarly, theEditTaskcomponent can also usev-modelto call other sub-components (such as form elements).This has to do with the fact that Changing props locally is considered an anti-pattern in Vue 2
If you want to change prop locally, what you should do now is declare a field in
datausingprops code> value as its initial value, and then change the copy :Vue.component('task', { template: '#task-template', props: ['list'], data: function () { return { mutableList: JSON.parse(this.list); } } });You can read more about it on Vue.js Official Guide
Note 1: Please note that you should not not for
propanddata使用相同的名称>,Right now:data: function () { return { list: JSON.parse(this.list) } } // WRONG!!Note 2: Since I think there is some confusion
aboutprops and reactivity, I suggest you take a look at this Thread