Я начал серию https://laracasts.com/series/learning-vue-step-by-step . Я остановился на уроке Vue, Laravel и AJAX с этой ошибкой:
vue.js: 2574 [Vue warn]: избегайте прямого изменения свойства, так как значение будет перезаписываться при каждом повторном рендеринге родительского компонента. Вместо этого используйте данные или вычисляемое свойство, основанное на значении реквизита. Пропуская мутирование: «список» (находится в компоненте)
У меня есть этот код в main.js
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
Я знаю, что проблема в create (), когда я перезаписываю реквизит списка, но я новичок в Vue, поэтому я совершенно не знаю, как это исправить. У кого-нибудь есть идеи, как (и, пожалуйста, объясните, почему) это исправить?
javascript
vue.js
vuejs2
Дариуш Чованьски
источник
источник
Ответы:
Это связано с тем фактом, что мутирование опоры локально считается анти-паттерном в Vue 2
Что вы должны сделать сейчас, если вы хотите локально изменить мутацию , это объявить поле в вашем поле,
data
которое используетprops
значение в качестве начального значения, а затем изменить копию:Вы можете прочитать больше об этом в официальном руководстве Vue.js
Примечание 1. Обратите внимание, что вы не должны использовать одно и то же имя для вашего
prop
иdata
, то есть:Примечание 2: Так как я чувствую , что есть некоторая путаница относительно
props
и реакционная способность , я предлагаю вам взглянуть на эту нитьисточник
Шаблон Vue
props
вниз иevents
вверх. Звучит просто, но легко забыть при написании пользовательского компонента.Начиная с Vue 2.2.0 вы можете использовать v-модель (с вычисленными свойствами ). Я обнаружил, что эта комбинация создает простой, чистый и согласованный интерфейс между компонентами:
props
передаваемый компоненту остается реактивным (т. Е. Он не клонируется и не требуетwatch
функции для обновления локальной копии при обнаружении изменений).Вычисленное свойство позволяет устанавливать и устанавливать и устанавливать отдельно. Это позволяет
Task
переписать компонент следующим образом:Свойство модели определяет, с чем
prop
связаноv-model
и какое событие будет генерироваться при изменениях. Затем вы можете вызвать этот компонент из родительского элемента следующим образом:Свойство
listLocal
computed обеспечивает простой интерфейс метода получения и установки в компоненте (думайте, что это частная переменная). Внутри#task-template
вы можете выполнить рендеринг,listLocal
и он останется реактивным (т. Е. ПриparentList
изменении он обновитTask
компонент). Вы также можете изменитьlistLocal
его, вызвав сеттер (например,this.listLocal = newList
), и он отправит изменения родителю.Что хорошо в этом шаблоне, так это то, что вы можете перейти
listLocal
к дочернему компонентуTask
(usingv-model
), а изменения от дочернего компонента распространятся на компонент верхнего уровня.Например, скажем, у нас есть отдельный
EditTask
компонент для некоторого типа модификации данных задачи. Используя тот жеv-model
и вычисленный шаблон свойств, мы можем перейтиlistLocal
к компоненту (используяv-model
):Если
EditTask
испускает изменение будет соответствующим образом позвонитьset()
наlistLocal
и тем самым распространить событие до уровня верхнего. Точно так жеEditTask
компонент может также вызывать другие дочерние компоненты (такие как элементы формы), используяv-model
.источник
Vue просто предупреждает вас: вы меняете реквизит в компоненте, но при повторном рендеринге родительского компонента «список» будет перезаписан, и вы потеряете все свои изменения. Так что это опасно.
Используйте вычисленное свойство вместо этого:
источник
Если вы используете Lodash, вы можете клонировать опору, прежде чем вернуть ее. Этот шаблон полезен, если вы изменяете эту опору как на родителя, так и на ребенка.
Допустим, у нас есть список опор в сетке компонентов .
В родительском компоненте
В дочернем компоненте
источник
Опоры вниз, события вверх. Это шаблон Vue. Дело в том, что если вы попытаетесь изменить пропуски, передаваемые от родителя. Он не будет работать, и он просто перезаписывается родительским компонентом. Дочерний компонент может генерировать только событие, чтобы уведомить родительский компонент о выполнении чего-либо. Если вам не нравятся эти ограничения, вы можете использовать VUEX (на самом деле этот шаблон будет засасывать сложную структуру компонентов, вам следует использовать VUEX!)
источник
Вы не должны изменять значение реквизита в дочернем компоненте. Если вам действительно нужно изменить его, вы можете использовать
.sync
. Именно так<your-component :list.sync="list"></your-component>
источник
Согласно VueJs 2.0, вы не должны мутировать пропеллер внутри компонента. Они только видоизменены своими родителями. Следовательно, вы должны определять переменные в данных с разными именами и обновлять их, наблюдая за фактическими данными. В случае, если реквизиты списка изменены родителем, вы можете проанализировать его и назначить его в mutableList. Вот полное решение.
Он использует mutableList для визуализации вашего шаблона, таким образом, вы сохраняете свой список в безопасности в компоненте.
источник
не меняйте реквизиты непосредственно в компонентах. если вам нужно изменить их, установите новое свойство, например:
И измените значение listClone.
источник
Ответ прост: вы должны прервать прямую мутацию, присвоив значение некоторым локальным переменным компонента (это может быть свойство данных, вычисленное с помощью геттеров, сеттеров или наблюдателей).
Вот простое решение с помощью наблюдателя.
Это то, что я использую для создания любых компонентов ввода данных, и это прекрасно работает. Любые новые данные, отправленные (v-модель (ed)) от родителя, будут отслеживаться наблюдателем значения и назначаться входной переменной, и после получения ввода мы можем перехватить это действие и передать входные данные родителю, предполагая, что данные вводятся. из элемента формы.
источник
Я тоже столкнулся с этой проблемой. Предупреждение ушло после того, как я использую
$on
и$emit
. Это что-то вроде использования$on
и$emit
рекомендуется отправлять данные из дочернего компонента в родительский компонент.источник
Если вы хотите поменять реквизит - используйте объект.
составная часть:
источник
Вы должны добавить вычисляемый метод, как это
component.vue
источник
Односторонний поток данных, согласно https://vuejs.org/v2/guide/components.html , компонент следует одностороннему потоку данных. Все реквизиты образуют одностороннюю привязку между дочерним свойством и родительским Во-первых, когда родительское свойство обновляется, оно передается дочернему элементу, но не наоборот, это предотвращает случайное изменение дочерних компонентов родительского, что может затруднить понимание потока данных вашего приложения.
Кроме того, каждый раз, когда родительский компонент обновляется, все реквизиты в дочерних компонентах обновляются с последним значением. Это означает, что вы не должны пытаться изменить опору внутри дочернего компонента. Если вы это сделаете .vue предупредит вас в консоли.
Обычно есть два случая, когда возникает соблазн мутировать реквизит: реквизит используется для передачи начального значения; потом дочерний компонент хочет использовать его как локальное свойство данных. Опора передается как необработанная ценность, которую необходимо преобразовать. Правильный ответ на эти случаи использования: Определите локальное свойство данных, которое использует начальное значение проп в качестве своего начального значения:
Определите вычисляемое свойство, которое вычисляется из значения проп:
источник
Реквизиты Vue.js не должны быть видоизменены, так как это считается Anti-Pattern в Vue.
Подход, который вам потребуется, - это создать свойство данных в вашем компоненте, которое ссылается на исходное свойство prop списка
Теперь к вашей структуре списков, которая передается компоненту, ссылаются и видоизменяют через
data
свойство вашего компонента :-)Если вы хотите сделать больше, чем просто проанализировать свойство списка, используйте свойство компонента Vue
computed
. Это позволит вам сделать более глубокие мутации для вашего реквизита.Приведенный выше пример анализирует ваш список поддержки и фильтрует его только для активных элементов списка, регистрирует его на предмет schnitts и хихикает и возвращает его.
примечание : оба шаблона
data
иcomputed
свойства указаны в шаблоне одинаково, напримерМожет быть легко предположить, что
computed
свойство (будучи методом) нужно вызывать ... это не такисточник
Может быть, это будет соответствовать вашим потребностям.
источник
Добавляя к лучшему ответу,
Установка реквизитов с помощью массива предназначена для разработки и создания прототипов, в производственном процессе убедитесь, что установлены типы реквизитов ( https://vuejs.org/v2/guide/components-props.html ) и задано значение по умолчанию, если реквизит не имеет был заселён родителем, как таковой.
Таким образом вы, по крайней мере, получаете пустой объект
mutableList
вместо ошибки JSON.parse, если он не определен.источник
Ниже приведен компонент снек-бара, когда я передаю переменную снэк-бара непосредственно в v-модель, как это, если она будет работать, но в консоли, она выдаст ошибку как
Избегайте прямого изменения свойства, так как значение будет перезаписываться при повторном рендеринге родительского компонента. Вместо этого используйте данные или вычисляемое свойство, основанное на значении реквизита.
Правильный способ избавиться от этой ошибки мутации - использовать watcher
Таким образом, в главном компоненте, где вы будете загружать эту закусочную, вы можете просто сделать этот код
Это сработало для меня
источник
Vue.js считает это анти-паттерном. Например, объявив и установив некоторые реквизиты, такие как
Таким образом, чтобы решить эту проблему, вы должны получить значение из реквизита для данных или вычисляемое свойство экземпляра Vue, например:
Это определенно будет работать.
источник
В дополнение к вышесказанному, для других, имеющих следующую проблему:
«Если значение реквизита не требуется и, следовательно, не всегда возвращается, переданные данные вернутся
undefined
(вместо пустых)». Что может испортить<select>
значение по умолчанию, я решил это, проверив, установлено ли значение вbeforeMount()
(и установите его, если нет) следующим образом:JS:
Html:
источник
Я хочу дать этот ответ, который поможет избежать использования большого количества кода, наблюдателей и вычисляемых свойств. В некоторых случаях это может быть хорошим решением:
Опоры предназначены для обеспечения односторонней связи.
Когда у вас есть модальная
show/hide
кнопка с опорой, лучшее решение для меня - это создать событие:Затем добавьте слушателя к модальному элементу:
(В этом случае опора
show
, вероятно, не нужна, потому что вы можете использовать легкийv-if="show"
прямо на базовый модальный)источник
Лично я всегда предлагаю, если вам нужно изменить мутацию, сначала передать их в вычисляемое свойство и вернуться оттуда, после чего можно легко изменить мутацию, даже при этом вы можете отслеживать мутацию винта, если он мутировал из другого. компонент тоже, или мы можем также посмотреть.
источник
Поскольку Vue props является односторонним потоком данных, это предотвращает случайное изменение дочерних компонентов состояния родителя.
Из официального документа Vue мы найдем 2 способа решения этой проблемы.
если дочерний компонент хочет использовать реквизиты в качестве локальных данных, лучше всего определить свойство локальных данных.
Опора передается как необработанная ценность, которую необходимо преобразовать. В этом случае лучше всего определить вычисляемое свойство, используя значение проп:
источник
ДА !, мутация атрибутов в vue2 - это анти-паттерн. НО ... Просто нарушай правила, используя другие правила, и иди вперед! Вам нужно добавить модификатор .sync к атрибуту вашего компонента в области видимости.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 Это просто, мы убиваем Бэтмена 😁
источник
Когда TypeScript - ваш предпочтительный язык. развития
и нет
источник