VUE属性透传实现

502 阅读1分钟

1.使用场景和props方式举例

在使用组件时,组件的传值往往通过props来实现,举例来说

这是一个element的输入框组件

  <template>
    <div>
      <el-input v-model="text" :placeholder="placeholder"
        :clearable="clearable"></el-input>
    </div>
  </template>
  props: {
      // 定义传值的placeholder,clearable
  }

在使用这个组件时 如果想给el-input加上属性可以使用props

<Input :placeholder='placeholder' :clearable="clearable"/>

  1. 以上的可能存在传值属性过多的问题,对此有另外一种方式传值-透传 以上述输入框组件为例

<Input :placeholder='placeholder' :clearable="clearable" >

我们不是用props的方式,首先在父组件使用input组件时直接添加属性,此时查看DOM元素可以发现节点中存在:placeholder='placeholder' :clearable="clearable"属性,只不过这些属性没有作用在el-input标签上,这时通过 v-bind="$attrs" 方式 让组件内部的标签获取到传值对应的属性

<template>
  <div>
    <el-input v-bind="$attrs" ></el-input>
  </div>
</template> 

这样就不需要时使用props方式来接受传值了

3.进阶问题--动态透传 以下是比较常见的开发场景(?可能常见)

<!-- 动态组件,根据 JSON 配置 调用 Input 或者 Select 组件等等 -->
<template>
  <div class="hello">
    <div v-for="(config, index) in configJsonArr" :key="config.type + index">
      <!-- 动态组件,根据配置中的 Type 来决定调用的是 Input 还是 Select -->
      <component :is="config.type" :configProps="config.props"></component>
    </div>
  </div>
</template>
<script>
import Input from './Input'
import Select from './Select'
export default {
  name: 'Config',
  components: {
    Input,
    Select
  },
  props: {
    // 动态组件 JSON schema 的配置
    configJsonArr: {
      type: Array,
      required: true,
      default: () => []
    }
  }
}
</script>

configJsonArr如下

[{
  type: 'Input',
  props: {
    placeholder: '我是默认值',
    clearable: true
  }
}, {
  type: 'Select',
  props: {
    placeholder: '我是默认值'
  }
}, {
  type: 'Input',
  props: {
    placeholder: '我是默认值',
    suffixIcon: 'el-icon-delete'
  }
}]

组件都是通过动态渲染而来的 此时 v-bind="$attrs" 这样的方式只能透传得到:configProps="config.props"这里面的对象结构,标签不能够解析成为属性

4.render函数 render函数能够接受属性对象 并解析成属性渲染

<template>
  <div class="hello">
    <div v-for="(config, index) in configJsonArr" :key="config.type + index">
      <!-- <component :is="config.type" :configProps="config.props"></component> -->
      <comp-form-item :configJson="config"></comp-form-item>
    </div>
  </div>
</template>
const CompFormItem = {
  components: {
    Input, Select
  },
  name: 'FormItem',
  props: {
    configJson: {
      required: true
    }
  },
  render (h) {
    return h(`${this.configJson.type}`, {
      props: {
        ...this.configJson.props || {}
      },
      attrs: {
        ...this.configJson.props || {}
      }
    })
  }
}

在父组件中绑定configJsonArr,在子组件中定义组件Item并接受configJsonArr,在Item组件接受数组的每一项(获取到了type,props),并使用render函数渲染每一项的(type,props)