Home  >  Q&A  >  body text

Vue 2 - Warning about changing props

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粉818306280P粉818306280393 days ago614

reply all(2)I'll reply

  • P粉715274052

    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:

    • Any 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). < /里>
    • Changes are automatically sent to the parent.
    • Can be used with multiple levels of components.

    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).

    reply
    0
  • P粉268654873

    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

    reply
    0
  • Cancelreply