vue2.0中,子组件修改父组件传递过来得props,该怎么解决?

vue2.0中,子组件中不能修改父组件的状态,否则在控制台中会报错。
但是经我测试发现,这仅限于props为非数组及对象等引用类型数据,譬如字符串,数字等
如果props是对象的话,在子组件内修改props的话,父组件是不会报错的。
测试代码如下:
parent.vue

<template>
  <div class="">
    <p>parent</p>
    <child :test="test"></child>
    <p>这是父组件中的data:{{test.hello}}</p>
  </div>
</template>
<script type="text/ecmascript-6">
  import Child from './child.vue'
  export default {
    data() {
      return {
          test: {
              hello: 1
          }
      }
    },
    components: {
      Child
    }
  }
</script>
<style>
</style>

child.vue

<template>
    <div class="">
      <p>child</p>
      <p>这是子组件中的props:{{test.hello}}</p>
      <input type="text" v-model="test.hello">
      <p></p>
    </div>
</template>
<script type="text/ecmascript-6">
    export default {
        props:{
          test: {
              type:Object
          }
        }
    }
</script>
<style>
</style>

运行parent.vue之后,我们可以看到如下的结果:

图片描述

我们在子组件的input中,直接绑定到props上,这样,我们修改input的内容,会发现,子组件的props被修改了,同时,父组件的data一样也被修改了,更关键的是,我们打开控制台,可以看到。没有报错。
这是不是违背了作者的子组件不修改props的意图?或者说,如果是传递的props的话,是不是就可以在子组件中修改props,从而达到修改父组件data的目的?但是结果就如作者所说,会导致父组件的data混乱,而且难以捕捉。请问,遇到这种情况,该怎么有效而又可靠的解决掉?

阅读 40.9k
10 个回答

如果非得需要修改传入的prop为对象的属性,而又不想破坏原对象,可以考虑深拷贝一下这个对象。

ES6提供的Object.assign({}, prop)的返回值就是一个全新的对象,操作这个新对象不会影响旧对象。如果不用ES6就自己递归实现拷贝器

1.给computed属性设置get和set方法,并利用Object.assign()浅克隆或者JSON.stringify()深度拷贝对象可以完美解决修改props传值问题,贴上代码段

computed:{
      dialogFormVisible:{
        get:function(){
          return this.addData=Object.assign({},this.dialogEditOrAddData)
        },
        set:function(newValue){
          return this.addData=newValue
        }
        
      }
    },
    

2.另外建议如果要修改props传入的值,用watch可以多次修改,watch监听对象得用深度监听贴上代码

watch:{
      dialogEditOrAddData:{//dialogEditOrAddData得在data中声明
        handler(oldVal,newVal){
          this.dialogFormVisible=newVal
        },
        deep:true
      }
    },

3.computed修改的值虽然get时是深度克隆对象,但是set时还是会修改父组件的值,所以如果是子组件修改后的值和父组件设置方法的值一致,第二次computed就不会触发拉

首先,组件间的数据传递只能是父到子,数据流向的单一保证了数据变化的可追踪性;如果子组件操作该值要求父组件作出相应变化时,那就子组件emit一个事件,父组件内捕获这个事件,然后在父组件内执行相应的变化;如果只是想通过props获取一个初始值,之后无论子组件如何操作该值都不会影响父组件的变化,那就在传入子组件数据的时候就进行一下处理(值引用类型数据无需处理,址引用数据进行一下深度拷贝Object.assign({},obj)或者JSON.parse(JSON.stringify(obj)))

尤大不反对这种方式,可以作为一个父子组件间双向通信的简易方案。

子组件修改父组件的prop,虽然报warning但也是可以成功运行的。

如果你想实现双向传递,首先考虑v-model,再考虑自定义事件。v-model仅仅是一个语法糖,他内部还是自定义事件。

如果你不想,那么设置temp变量,缓存prop过来的数据,再操作temp即可。

不是有computed么

新手上路,请多包涵

对象和数组都是引用传递,字符串数字属于值传递

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏