Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-

单向数据流

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解

另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着不应该在子组件内部改变 prop。如果这么做了,Vue 会在控制台给出警告

下面是一个典型例子

<div id="example">
  <parent></parent>
</div>
<script>
var childNode = {
  template: `
  
子组件数据

{{childMsg}}

`
, props:['childMsg'] } var parentNode = { template: `
父组件数据

{{msg}}

`
, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>

父组件数据变化时,子组件数据会相应变化;而子组件数据变化时,父组件数据不变,并在控制台显示警告Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-_第1张图片
修改子组件数据时,打开浏览器控制台会出现下图所示警告提示
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-_第2张图片

修改prop数据

修改prop中的数据,通常有以下两种原因

1、prop 作为初始值传入后,子组件想把它当作局部数据来用

2、prop 作为初始值传入,由子组件处理成其它数据输出

[注意]JS中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态

对于这两种情况,正确的应对方式是

1、定义一个局部变量,并用 prop 的值初始化它

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

但是,定义的局部变量counter只能接受initialCounter的初始值,当父组件要传递的值发生变化时,counter无法接收到最新值

<div id="example">
  <parent></parent>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
  template: `
  
子组件数据

{{temp}}

`
, props:['childMsg'], data(){ return{ temp:this.childMsg } }, }; var parentNode = { template: `
父组件数据

{{msg}}

`
, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>

下面示例中,除初始值外,父组件的值无法更新到子组件中
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-_第3张图片

2、定义一个计算属性,处理 prop 的值并返回

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

但是,由于是计算属性,则只能显示值,而不能设置值

<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
  template: `
  
子组件数据

{{temp}}

`
, props:['childMsg'], computed:{ temp(){ return this.childMsg } }, }; var parentNode = { template: `
父组件数据

{{msg}}

`
, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>

下面示例中,由于子组件使用的是计算属性,所以,子组件的数据无法手动修改Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-_第4张图片
 3、更加妥帖的方案是,使用变量储存prop的初始值,并使用watch来观察prop的值的变化。发生变化时,更新变量的值

<div id="example">
  <parent></parent>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
  template: `
  
子组件数据

{{temp}}

`
, props:['childMsg'], data(){ return{ temp:this.childMsg } }, watch:{ childMsg(){ this.temp = this.childMsg } } }; var parentNode = { template: `
父组件数据

{{msg}}

`
, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>

父组件改变,子组件也改变;反之,子组件改变,父组件不变
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-_第5张图片

你可能感兴趣的:(vue采坑)