Vue 2-мутирующий реквизит vue-предупредить



Я начал https://laracasts.com/series/learning-vue-step-by-step серия. Я остановился на уроке Vue, Laravel и AJAX С этой ошибкой:



vue.js:2574 [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: "list" (found in component <task>)


у меня есть этот код главная.js



Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})


Я знаю, что проблема в created () когда я перезаписываю список prop, но я новичок в Vue, поэтому я совершенно не знаю, как это исправить. У кого-нибудь есть идея, как (и, пожалуйста, объясните, почему) исправить это?

698   15  

15 ответов:

это связано с тем, что локальная мутация опоры считается анти-шаблоном в Vue 2 (см. здесь)

что вы должны сделать сейчас, если вы хотите мутировать опору локально, чтобы объявить поле в data использует props значение в качестве начального значения, а затем изменить копию:

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    data: function () {
        return {
            mutableList: JSON.parse(this.list);
        }
    }
});

пожалуйста, смотрите также этот вопрос здесь

надеюсь, что это помогает


Примечание 1: примите во внимание, что, согласно этот пост вы должны не попробуйте использовать то же имя для вашего prop и data, то есть:

data: function () { return { list: JSON.parse(this.list) } // WRONG!!

примечание 2: С я чувствую, что есть некоторая путаница о props и активность, Я предлагаю вам взглянуть на этой thread

Vue просто предупреждает Вас: Вы меняете опору в компоненте, но когда родительский компонент повторно отображает, "список" будет перезаписан, и вы потеряете все свои изменения. Так что это опасно.

использовать вычисляемое свойство, а как это:

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    computed: {
        listJson: function(){
            return JSON.parse(this.list);
        }
    }
});

реквизит вниз, события. Это модель Ву. Дело в том, что если вы попытаетесь мутировать реквизит, передаваемый от родителя. Он не будет работать, и он просто перезаписывается повторно родительским компонентом. Дочерний компонент может только выдавать событие, чтобы уведомить родительский компонент о выполнении sth. Если вам не нравятся эти ограничения, вы можете использовать VUEX(на самом деле этот шаблон будет всасывать сложную структуру компонентов, вы должны использовать VUEX!)

Если вы используете Lodash, вы можете клонировать опору перед ее возвратом. Этот шаблон полезен, если вы измените эту опору как на родителя, так и на ребенка.

Допустим, у нас есть проп список компонент решетки.

В Родительском Компоненте

<grid :list.sync="list"></grid>

В Дочернем Компоненте

props: ['list'],
methods:{
    doSomethingOnClick(entry){
        let modifiedList = _.clone(this.list)
        modifiedList = _.uniq(modifiedList) // Removes duplicates
        this.$emit('update:list', modifiedList)
    }
}

вы не должны изменять значение реквизита в дочерний компонент. Если вам действительно нужно изменить его, вы можете использовать .sync. Просто так

<your-component :list.sync="list"></your-component>

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.$emit('update:list', JSON.parse(this.list))
    }
});
new Vue({
    el: '.container'
})

согласно VueJs 2.0, вы не должны мутировать опору внутри компонента. Они только мутировали от своих родителей. Поэтому вы должны определить переменные в данных с разными именами и обновлять их, наблюдая за фактическими реквизитами. В случае, если список prop изменяется родителем, вы можете проанализировать его и назначить его mutableList. Вот полное решение.

Vue.component('task', {
    template: ´<ul>
                  <li v-for="item in mutableList">
                      {{item.name}}
                  </li>
              </ul>´,
    props: ['list'],
    data: function () {
        return {
            mutableList = JSON.parse(this.list);
        }
    },
    watch:{
        list: function(){
            this.mutableList = JSON.parse(this.list);
        }
    }
});

Он использует mutableList для визуализации вашего шаблона, таким образом, вы сохраняете свой список в безопасности деталь.

я столкнулась с этой проблемой, а также. Предупреждение ушло после того, как я использую $on и $emit. Это что-то вроде use $on и $emit рекомендуется отправлять данные из дочернего компонента в родительский компонент.

шаблон Vue прост:props и events вверх. Это звучит просто, но легко забыть при написании пользовательского компонента.

начиная с Vue 2.2.0 вы можете использовать v-модельвычисляемые свойства). Я считаю, что эта комбинация создает простой, чистый и последовательный интерфейс между компонентами:

  • любой props переданный вашему компоненту остается реактивным (т. е. он не клонирован и не требует watch функция обновления локальной копии при обнаружении изменений).
  • изменения автоматически передаются родителю.
  • может использоваться с несколькими уровнями компонентов.

вычисленное свойство позволяет отдельно определять сеттер и геттер. Это позволяет Task компонент, который будет переписан следующим образом:

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 модель свойство определяет prop связан с v-model и какое событие будет излучаться на изменения. Затем вы можете вызвать этот компонент из родительского объекта следующим образом:

<Task v-model="parentList"></Task>

The listLocal вычисляемое свойство обеспечивает простой интерфейс getter и setter в компоненте (подумайте об этом как о частной переменной). Внутри #task-template вы можете оказать listLocal и он будет оставаться реактивным (т. е., если parentList изменения он будет обновлять Task компонент). Вы также можете мутировать listLocal вызывая сеттер (например, this.listLocal = newList) и он будет излучать измените на родителя.

что действительно здорово в этом шаблоне, так это то, что вы можете пройти listLocal к дочернему компоненту Task (через v-model), и изменения от дочернего компонента будут распространяться на компонент верхнего уровня.

например, скажем, у нас есть отдельная EditTask компонент для выполнения некоторого типа модификации данных задачи. С помощью того же v-model и вычисленные свойства шаблона мы можем передать listLocal компонент (используя v-model):

<script type="text/x-template" id="task-template">
    <div>
        <EditTask v-model="listLocal"></EditTask>
    </div>
</script>

если EditTask выдает изменение, которое он соответствующим образом вызовет set() on listLocal и тем самым распространить событие на высшем уровне. Точно так же,EditTask компонент также может вызывать другие дочерние компоненты (например, элементы формы) с помощью v-model.

Если вы хотите мутировать реквизит - использовать объект.

<component :model="global.price"></component>

компоненты:

props: ['model'],
methods: {
  changeValue: function() {
    this.model.value = "new value";
  }
}

вам нужно добавить вычисленный способ такой

односторонний поток данных, согласно https://vuejs.org/v2/guide/components.html, компонент следует в одну сторону поток данных, Все реквизиты образуют одностороннюю привязку между дочерним свойством и родительским, когда родительское свойство обновляется, оно будет стекать к дочернему, но не наоборот, это предотвращает случайное изменение дочерних компонентов родительского, что может затруднить понимание потока данных вашего приложения.

кроме того, каждый раз родительский компонент обновляет все реквизиты в дочерних компонентах будет обновлено последнее значение. Это означает, что вы не должны пытаться мутировать опору внутри дочернего компонента. Если ты это сделаешь .вю будет предупреждать вас в приставка.

обычно есть два случая, когда заманчиво мутировать опору: Prop используется для передачи начального значения; дочерний компонент хочет использовать его в качестве локального свойства данных впоследствии. Опора передается как необработанное значение, которое должно быть преобразованный. Правильный ответ на эти случаи использования:: Определите локальное свойство данных, которое использует начальное значение prop в качестве начального значения:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

определите вычисленное свойство, которое вычисляется из значения опоры:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Не меняйте реквизит непосредственно в компонентах.если вам нужно изменить его, установите новое свойство следующим образом:

data () {
    return () {
        listClone: this.list
    }
}

и изменить значение listClone.

Vue.JS props не должны мутировать, поскольку это считается анти-шаблоном в Vue.

подход, который вам нужно будет принять, - это создание свойства данных на вашем компоненте, которое ссылается на оригинал prop собственность список

props: ['list'],
data: () {
  return {
    parsedList: JSON.parse(this.list)
  }
}

теперь ваша структура списка, которая передается компоненту, ссылается и мутирует через data свойства компонента :-)

если вы хотите сделать больше, чем просто разобрать свой список затем свойство использует компонент Vue'computed собственность. Это позволит вам сделать более глубокие мутации для вашего реквизита.

props: ['list'],
computed: {
  filteredJSONList: () => {
    let parsedList = JSON.parse(this.list)
    let filteredList = parsedList.filter(listItem => listItem.active)
    console.log(filteredList)
    return filteredList
  }
}

приведенный выше пример разбирает ваш список prop и фильтрует его до только активный list-tems, выходит из системы для шнитца и хихикает и возвращает его.

Примечание: как data & computed свойства ссылаются в шаблоне то же самое, например

<pre>{{parsedList}}</pre>

<pre>{{filteredJSONList}}</pre>

It можно легко подумать, что a computed свойство (метод) должен быть вызван... это не

Vue.Яш считает, что это является анти-паттерн. Например, объявление и установка некоторых реквизитов, таких как

this.propsVal = 'new Props Value'

таким образом, чтобы решить эту проблему, вы должны принять значение из реквизитов в данные или вычисленное свойство экземпляра Vue, например:

props: ['propsVal'],
data: function() {
   return {
       propVal: this.propsVal
   };
},
methods: {
...
}

это определенно будет работать.

En este código, estoy usando un filtro para cada lista dentro de un component. declaro УНА vaviable сайт buscar-де-форма местной Аль сайт componente г крео ООН методо компьютерная пункт ГПС Ла листа г filtrarla..

Vue.component('comun-list',{
            props: ['list'],
            data: function () {
              return {
                buscar: '',
              }
            },
            template: `<ul class="list-group">
                            <li class="list-group-item">
                                <input type="text" v-model="buscar" class="form-control" />
                            </li>
                            <li v-for="item in buscarList" class="list-group-item">
                                {{item.title}}
                            </li>
                        </ul>`,
            computed: {
                buscarList: function(){
                    return this.list.filter((item) => item.title.includes(this.buscar));
                },
            },
        });

Comments

    Ничего не найдено.