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, поэтому я совершенно не знаю, как это исправить. У кого-нибудь есть идея, как (и, пожалуйста, объясните, почему) исправить это?
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()onlistLocalи тем самым распространить событие на высшем уровне. Точно так же,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