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?
P粉7152740522023-10-14 09:15:14
Vue modes are props
down, events
up. 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:
props
passed to the component remains responsive (i.e., it will not be cloned, nor will a watch
function 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 Task
component 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) } } } })The
model property defines the associated prop
and v-model
, and which event will be emitted when changed. You can then call this component from the parent component like this:
<Task v-model="parentList"></Task>
listLocal
Computed properties provide a simple getter and setter interface within the component (think of them as private variables). In #task-template
you can render listLocal
and it will remain reactive (i.e. if parentList
changes, it will update Task< /代码> component). You can also change the
listLocal
by 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 listLocal
to a child component of Task
(using v-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 EditTask
component that makes some type of modification to task data. By using the same v-model
and computed property pattern, we can pass listLocal
to the component (using v-model
):
<script type="text/x-template" id="task-template"> <div> <EditTask v-model="listLocal"></EditTask> </div> </script>
If the EditTask
emits a change, it will appropriately call set()
on the listLocal
, thereby propagating the event to the top level. Similarly, the EditTask
component can also use v-model
to call other sub-components (such as form elements).
P粉2686548732023-10-14 00:33:06
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 data
using props 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 prop
and data
,Right now:
data: function () { return { list: JSON.parse(this.list) } } // WRONG!!
Note 2: Since I think there is some confusion about
props and reactivity, I suggest you take a look at this Thread