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

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

image.png

原因:

子组件改了父组件的值

避免修改父组件传过来的值

image.png

注意: 如果value是obj,需要进行深拷贝。


可以参考: https://blog.csdn.net/u013948858/article/details/118342541

image.png

文章目录

1. 需求及报错

2. 分析原因

2.1 这是什么原因造成?

3. 解决方案: 使用 v-on 明确实现修改方式

4. 参考

1. 需求及报错

需求: 使用的场景是:A 组件中引用 B 组件,使用 v-model 给 B 传递参数,B 使用 props: { value } 接收内容,在 B 中根据逻辑直接修改并赋值 value, 事件触发后在浏览器 console 里看到报错,内容如下:

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: "value"

2. 分析原因

从报错内容上来看,我们改动了子组件中引用的父组件的变量,也就是 props 中的数据,是不能这么操作的;


从提示的信息上看,使用 mutated 是否可行?


在 Vue2 中组件 props 中的数据只能单向流动,即只能从父组件通过组件的 DOM 属性 attribute 传递 props 给子组件,子组件只能被动接收父组件传递过来的数据,并且在子组件中,不能修改由父组件传来的 props 数据。


组件内不能修改props的值,同时修改的值也不会同步到组件外层,即调用组件方不知道组件内部当前的状态是什么


2.1 这是什么原因造成?

在 vue1.x 版本中利用 props 的 twoWay 和 .sync 绑定修饰符就可以实现 props 的双向数据绑定。


在 vue2.0 中移除了组件的 props 的双向数据绑定功能,如果需要双向绑定需要自己来实现。

在 vue2.0 中组件的 props 的数据流动改为了只能单向流动,即只能由(父组件)通过组件的 v-bind:attributes 传递给(子组件),子组件只能被动接收父组件传递过来的数据,并在子组件内不能修改由父组件传递过来的 props 数据。


官方文档解释:


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

虽然废弃了props的双向绑定对于整个项目整体而言是有利且正确的,但是在某些时候我们确实需要从组件内部修改props的需求


在 Vue2.0 中,实现组件属性的双向绑定方式(算不上是绑定了,算是异步修改), 可使用如下方法


v-model 指令或 .sync 修饰符

将修改属性的方法通过 v-bind 传给子组件调用,子组件直接按方法使用即可

将修改属性的方法通过 v-on 传递给子组件调用,使用 $emit() 实现回调修改

或者使用 this.$parent 去修改

3. 解决方案: 使用 v-on 明确实现修改方式

也是为了代码可读性


不要直接修改从父组件传过来的 props 数据,在data函数中重新定义一个变量,将props数据数据赋值在data变量上,后面修改data变量即可。如下:


B 组件接受 A组件的参数

name: "B",
props: {
  father: {
    type: String,
    default: null
  }
}
data(){
  return{
    father_a : this.father
  }
}

如果想要监听 A 组件中传递过来的变量,从而修改 B 组件中的某个数据,可以使用 watch 这个监听函数来监听。如下:

name: "B",
props: {
  father: {
    type: String,
    default: null
  }
}
data(){
  return{
    father_a: this.father
    son: ''
  }
}
//监听函数,只要从父组件中传过来的father变量发生变化,
//子组件中定义的son变量就会赋值为“儿子”
watch:{
  father(val, valOld){
    this.son = "儿子"
  }
}
如果 
B
 想修改 
A
 传递过来的属性可以使用 
$emit
A
<B :father="a" @change="changeA" />
export default {
  name: 'A',
  data() {
    return {
      a: 'A的变量'
    }
  },
  methods: {
    changeA(val) {
      this.a = val
    }
  }
} 
<script>
export default {
  name: 'B',
  props: {
    father: {
      type: String,
      default: null
    }
  },
  data() {
  },
  watch:{
    father(val, valOld){  // 这里也可以在 data 定义变量 并将 father 赋值给他, 在这里监控这个变量
      // 这里做如果 father 变量变化了,子组件需要处理的逻辑
    }
  },
  methods: {
    changeAFather() { // 谁来调用它? 是子组件的业务操作
      this.$emit('change', val)
    }
  }
}
</script>
至此,子组件内数据与父组件的数据的双向绑定,组件内外数据的同步:
组件内部自己变了告诉外部,外部决定要不要变。
vue1.0
 数据双向绑定在 
vue2.0
 版本中被抛弃了呢?通过案例也可以发现双向绑定的 
props
 代码多,不利于组件间的数据状态管理,尤其是在复杂的业务中更是如此,不易理解和阅读其中的逻辑,所以尽量不使用这种方式的双向绑定,过于复杂的数据处理使用vuex来进行数据管理。

 


相关文章
|
6月前
|
JavaScript
鬼火起~为什么报错[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the
鬼火起~为什么报错[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the
|
6月前
|
JavaScript
Property “selectedItemIndex“ was accessed during render but is not defined on instance. 报错解决
Property “selectedItemIndex“ was accessed during render but is not defined on instance. 报错解决
662 0
|
3月前
|
开发工具 git
Stylelint——Unexpected unknown pseudo-class selector ":deep" selector-pseudo-class-no-unknown
新项目制定规范接入了stylelint,并通过husky在git提交时去触发检测修复,使用`:deep()`的时候却发现了报错;
134 1
Unknown custom element: <add-employee> - did you register the component correctly? For red cursive c
原因: 1.组件名没写对(导入和注册不对应) 2.components少写了个s 3.组件命名最好是驼峰命名 4.导入时语法错误 5.代码中有两个components,后一个的值把前一个覆盖了 6.组件直接循环套用了
101 0
|
6月前
|
小程序 JavaScript
Avoid mutating a prop directly since the value will be overwritten whenever the parent comp
Avoid mutating a prop directly since the value will be overwritten whenever the parent comp
|
JavaScript
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent .(二)
1.在data中声明一个变量接收props的值,然后再去改变data里的这个值 2. 用computed属性 3.用data保存数据,watch监听
|
JavaScript
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent .(一)
大致意思就是props接收到的从父组件传过来的tableData不能直接修改。
148 0
|
JavaScript 算法 前端开发
Property xxx was accessed during render but is not defined on instance
目前el-form的model主要用表单验证的,也就是配合el-form的rules和el-form-item的prop来使用的。不信的话,你可以增加一个rules和prop(为了调用验证方法,也el-form也加一个ref属性,相当于id或者class选择器的意思),但是不写model,然后验证的话,会提示缺少model,导致无法验证成功。
Property xxx was accessed during render but is not defined on instance
|
JavaScript
【解决方案】[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the pa
【解决方案】[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the pa
1719 0