Vue2.0 之props是数据绑定出错

背景

在使用Vue进行组件开发时,对于父组件传递过来的props属性,在子组件内部对这个值进行了更改,就会出现如下的错误信息:

[Vue warn]: 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: "xxx"


错误原因

在Vue2.X中,传入的props属性是不允许改变的,因为在新的渲染机制中,每当父组件重新渲染时,子组件都会被重新覆盖,所以props属性,在子组件内部应该被看做是不可变对象。所以我们必须借助中间变量来做缓冲,通过中间变量的改变发送事件给父组件,父组件接收到后,再对props进行更改。

案例

在实现公司内部组件时,我引用了element-ui的Dialog组件,为了方便组件的复用,我将一些基础属性封装在了一个自定义组件中,大致的结构如下:
Vue2.0 之props是数据绑定出错_第1张图片

  • 外部Index是用于组装自定义的组件
  • 自定义组件是一些可以复用的基本功能组件
  • 最里面的是引用的elementUI

为了控制弹出框的显示情况,所以我定义了一个Visible属性,
Visible的流向是:
Vue2.0 之props是数据绑定出错_第2张图片

在element-ui组件中 ,控制显示的一般会加上这个属性:visible.sync="visible"
这个意思是说elementui组件在内部改变visible之后会通知父组件visible属性更新了。它的变化会回传给父组件,所以当时在自定义组件中拿到这个值就对其进行操作,发现报错了。此时的数据流向如下:
Vue2.0 之props是数据绑定出错_第3张图片
这个属性是Index传进来的,所以我们没有经过Index,在自定义组件就对其进行了修改,所以不符合Vue对于属性数据单向传递的规则,正确的做法是像这样:
Vue2.0 之props是数据绑定出错_第4张图片

但是由于elementUI直接就将变化给回传了,所以我们不能直接传给Index组件,需要借助一个中间变量来接受这个值,然后把这个变化回传给Index组件,告诉Index自定义组件需要更新。

解决方式

首先我们顶一下Index组件需要传的值:

<user-dialog :showDialog.sync="dialogTableVisible" :ruleForm="ruleForm" v-if="dialogTableVisible"
@closeDialog="closeUserDialog"></user-dialog>

dialogTableVisible属性传入到user-dialog自定义的组件中

自定义的组件

  props: {
      showDialog: {
             type: Boolean,
             default: false
         }       
 },
 data(){
 	return {
 		//show控制elementui的变化
 		show: false,
	}
 }
 //创建时,赋值
 created() {
  	this.show = this.showDialog;
 },

我们借助show作为中转变量,当show发生变化时,我们发送事件给Index组件
所以,在关闭elementui时,触发一个回调函数:

closeDialog() {
     this.show = false;
     this.$emit('closeDialog');
},

父组件可以通过监听这个事件来关闭自定义组件:

<user-dialog :showDialog.sync="dialogTableVisible" :ruleForm="ruleForm" v-if="dialogTableVisible"
@closeDialog="closeUserDialog"></user-dialog>

事件方法:

closeUserDialog() {
 	this.dialogTableVisible = false;
},

解决方式二

通过事件Bus来传递事件

import Vue from 'vue'
const Bus = new Vue()
var app= new Vue({
    el:'#app',
   data:{
    Bus
    }  

})

直接创建一个空Vue实例,作为消息总线承载体,然后在子组件中通过
this.$root.Bus.$on(),this.$root.Bus.$emit()来调用.
不需要走props,子组件改变就调用$emit('xxx')发送事件
父组件只需要监听$on('xxx')然后操作传入的属性值即可。

你可能感兴趣的:(Vue,JAVASCRIPT笔记)