VUE中props复杂对象如何传递

新手上路,请多包涵

问题描述

为了更好的封装组件,和让整个程序看起来更友好和规范一些,我准备将每个组件需要传递的信息都通过来ComponentData封装
如,有个组件为BaseTable:

  props: {
    ComponentData: {
      tableconfgName: "",
      sql: "",
      addflag: true,
      editflag: true,
      delflag: true
    }
  },

父组件中通过:

<BaseTable :ComponentData="basetable"/>
 basetable: {
        tableconfgName: "",
        delflag: true,
        sql: ""
      }

来给组件传递,但组件不能获得相关信息,而且我通过组件的watch方法也尝试过,不能监听父组件给组件传值

 watch: {
    "ComponentData.sql": function(n, o) {
      console.log(n);
        }
      }

请教各位大神有无更好的方法,因为我写的功能很复杂,一个页面中会用到大量的子定义组件,父子组件会涉及到大量的参数传递,如果不能很好的规划传参信息,程序代码很混乱。

问题出现的环境背景及自己尝试过哪些方法

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 32.1k
7 个回答

今天封装组件也遇到了和你一样的问题,我自己想到了一个解决方法,就是通过computed再定义一个对象,用来合并父组件传进来的值和默认值,我之前那遇到的问题是在props里面table对象定义了很多的默认值,父组件要是不传值就用默认值,要是传值了部分值,所有的默认值都被替换掉了,这不是我想要的,我想要的是传了值就替换,不传的保留我原来的默认值,所以想到了这个办法

props: {
    table: {
      type: Object,
      default: () => {}
    }
  }
computed: {
    // 表格参数
    baseTable() {
      let table = this.table ? this.table : {}
      let defaultTable = {
        objCode: '', // 接口号
        objParam: {}, // 传入接口的参数
        columns: [], // 表格列数据
        data: [], // 表格数据
        showPagination: true, // 是否显示分分页
        showSerialNumber: true, // 是否显示序号
        showCheckbox: true, // 是否显示复选框
        isSelectOnload: true, // 加载表格是否选中第一行
        length: 10 // 分页每页显示的页数
      }
      return Object.assign({}, defaultTable, table)
    }
 }
新手上路,请多包涵

有两个方法:
1.开启watch深度观察模式,这种模式能够监听所观察对象中每一个属性的变化,但因为需要层层递归所以性能也稍微有减弱,所以在使用的时候如果能够去监听对象中特定的属性能够少为避免消耗太大,如果需要第一次创建组件就立即得到计算,还可以设置immediate属性:

watch: {
  ComponentData: {
    handler (n, o) {
      console.log(n)
    },
    deep: true
  },
  'ComponentData.sql': {
    handler (n, o) {
      console.log(n)
    },
    deep: true,
    immediate: true
  }
}

2.更健壮的Vuex方案,把状态统一管理,子组件只要采用计算属性去得到store储存的变量就可以,还方便以后在其他组件中复用这些变量,可扩展性强,并且统一管理可以把业务代码和视图逻辑分开,实现更好的代码组织。

computed: {
    sql () {
        return ComponentData.sql
    }
},
watch: {
    sql () {
        console.log('has Change')
    }
}
props: {
  ComponentData: {
    type: Object,
    default: () => ({
      tableconfgName: '',
      sql: '',
      addflag: true,
      editflag: true,
      delflag: true,
    }),
  },
},
watch: {
  'ComponentData.sql'(n, o) {
    console.log(n);
  },

这样写可以直观的看到需要的数据结构,并且不用开启deep就支持ComponentData.sql属性监听

参考两个官方注意事项
clipboard.png

clipboard.png

可以考虑在通信时转成字符串 JSON.stringify(),子组件接收后 watch 也是字符串,在子组件内使用时通过 JSON.parse() 转成对象

推荐问题
宣传栏