Vuejs. Мутация свойства в дочернем компоненте не вызывает предупреждения. Интересно, почему

Я заметил что-то странное с мутацией пропов (Vue 2.6).

Следует избегать изменения props непосредственно в дочернем компоненте, так как это вызовет следующее известное предупреждение

Избегайте изменения свойства напрямую, так как значение будет перезаписано ....

Итак, если в моем родительском компоненте у меня есть такие данные, как

exemple: "Hello World"

который я передал как опору дочернему компоненту. Если в этом дочернем компоненте я делаю что-то вроде

this.exemple = "Hello World!"

Я получаю предупреждение. Справедливо. Теперь я заметил, что если данные в родительском объекте являются такими объектами, как

exemple : {message : "Hello World"}

и что в детстве я делаю что-то подобное

this.exemple.message = "Hello World!"

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

Интересно почему. Почему мутация prop распространяется на родителя в одном случае, но не в другом? Может быть, это как-то связано с тем, как javascript хранит эту переменную? Является ли использование этого трюка хорошей практикой?


person Francois    schedule 27.11.2020    source источник
comment
Вы можете отправить изменение this.$emit('update:example', 'Hello!') ... и в родительской синхронизации это :example.sync="example" ... таким образом, vue узнает об изменении и может выполнить любое необходимое реактивное действие.   -  person Washington Guedes    schedule 27.11.2020


Ответы (3)


Почему мутация prop распространяется на родителя в одном случае, но не в другом? Может быть, это как-то связано с тем, как javascript хранит эту переменную?

да. Переменные ссылки JavaScript, такие как объекты и массивы, не изменяют свои ссылки, когда вы изменяете их свойства / значения. Это означает, что родитель также может получить доступ к измененным свойствам, потому что он также имеет доступ к ссылке. А Vue выдает предупреждение о мутации пропа только при изменении ссылки.

Предупреждение:

this.prop = {}

Без предупреждения:

this.prop.id = 5

Является ли использование этого трюка хорошей практикой?

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


Хорошо, но почему Vue не предупреждает об этих изменениях?

Рассмотрим объект с 1000 свойствами или массив с 1000 элементами. Vue пришлось бы тщательно проверять все 1000 на наличие изменений, и быстрого способа сделать это нет, потому что каждый элемент должен индивидуально сравниваться со старым значением. Это повлияет на производительность и, вероятно, сделает многие приложения непригодными для использования.


Вот комментарий к тема от члена команды Vue Bolerodan:

Обычно этого делать не следует. Это может / могло вызвать неожиданные ошибки в вашем коде. Как правило, вы должны сделать копию своего объекта, изменить ее, а затем передать вверх родительскому объекту (как я полагаю, вы упомянули в своем последнем абзаце). Это метод, который я использую, и это общее мнение о подходе «сверху вниз, выбросить вверх».

person Dan    schedule 27.11.2020

Очень простой ответ: вы изменяете reference value, и Vue не отслеживает весь reference, а только проверяет адрес, на который находится ссылка. Поэтому, если вы повторно присвоите это значение, он предупредит вас.

Хороший пример для понимания поведения - понимание через объявление переменной const

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

const a = 'Foo' // Primitive value

a = 'bar' // voilation
 
const b = { // Reference value
 name: 'Foo' 
}

b.name = 'Bar' // It's good

console.log(b)

b = {} // re-assign is voilation

person Satyam Pathak    schedule 27.11.2020

Потому что предотвращение мутаций улавливает только прямые назначения реквизиту - оно не улавливает манипуляции с его свойствами. Идея состоит в том, что если вы присваиваете новые значения опоре - вы присваиваете prop, а не переменную, которая находится в родительском компоненте Vue, который питает опору.

Как только что-то в родительском компоненте обновит переменную кормления - опора будет обновлена ​​этим новым значением, а значение, которое вы присвоили опоре в своем дочернем компоненте, будет перезаписано.

Если вы скармливаете опору объект, а затем изменяете свойство внутри опоры в своем дочернем компоненте - это повлияет на тот же объект внутри родительского компонента. Но если вы попытаетесь назначить новый объект опоре в своем дочернем компоненте, вы должны получить такое же предупреждение о мутации реквизита.

person IVO GELOV    schedule 27.11.2020