При использовании props в компонентах следует учитывать, что данные в props представляют однонаправленный поток данных от родительского компонента к дочерним компонентам. Изменение свойства родителя приведет к изменению в дочерних компонентах. Однако дочерние компоненты не могут изменить свойство родителя. То есть поток данных идет только в одном направлении: родителя к потомкам. Кроме того, если мы попробуем изменить в дочерних компонентах значения, переданные через props, то на консоль браузера будет выведено предупреждение о том, что это не следует делать.
Более того при любом обновлении родительского компонента у дочерних компонентов обновляются значения, передаваемые через props. Например, рассмотрим следующую ситуацию:
<!DOCTYPE html> <html> <head> <title>Компоненты Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <h2>Hello, {{name}}</h2> <useredit :user="name"></useredit> <button v-on:click="resetName">Set Name</button> </div> <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script> <script> Vue.component('useredit', { props: ["user"], template: '<div><input type="text" v-model="user" /><p>Name: {{user}}</p></div>' }); new Vue({ el: "#app", data: { name: 'Tom' }, methods:{ resetName: function(){ this.name = 'Bob'; } } }); </script> </body> </html>
Из родителя - объекта Vue в компонент useredit через props передается значение name. В этом компоненте мы можем попробовать управлять переданным значением через поле ввода и механизм двусторонней привязки:
<input type="text" v-model="user" />
Но если мы попробуем изменить через поле ввода данное значение, то оно изменится только в рамках компонента useredit, а на консоль будет выведено предупреждение:
Значение свойства name в родительском объекте Vue никак не будет затронуто. Почему так происходит? Дело в том, что данные простых типов - String, Number, Boolean передаются по значению, то есть в дочерний компонент передается копия значения. И в данном случае в компонент useredit как раз передается копия строки name. Соответственно все действия с этой копией никак не повлияют на родительский объект.
В отличие от простых типов сложные объекты и массивы передаются по ссылке. Поэтому из дочерних компонентов мы можем изменять массивы или сложные объекты, которые определены в родительских объектах.
Более того в объекте Vue посредством нажатия кнопки мы можем вызвать метод resetName, который изменит свойство name с Tom на Bob:
То есть несмотря на то, что внутри компонента useredit мы меняем значение из props, но изменение родителя - объекта Vue приведет к изменению дочернего компонента.
Однако могут быть ситуации, когда нам все таки нужно изменить значения в props и при этом не допустить изменения этих значений извне. Что делать в этом случае? В этом случае мы можем определить локальную переменную. Через props устанавливается ее начальное значение, и затем компонент работает только с этой переменной:
<div id="app"> <h2>Hello, {{name}}</h2> <useredit :user="name"></useredit> <button v-on:click="resetName">Set Name</button> </div> <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script> <script> Vue.component('useredit', { props: ["user"], data: function () { return { userName: this.user} }, template: '<div><input type="text" v-model="userName" /><p>Name: {{userName}}</p></div>' }); new Vue({ el: "#app", data: { name: 'Tom' }, methods:{ resetName: function(){ this.name = 'Bob'; } } }); </script>
Теперь все действия будут идти с локальной переменной userName. Значения из props в компоненте не будут изменяться, а изменения в родительском компоненте никак не повлияют на значение переменной userName.