美文网首页
Vue自定义组件

Vue自定义组件

作者: halapro_liu | 来源:发表于2021-08-18 16:49 被阅读0次

    使用render函数实现

    export default {
      props: {
        cols: { // 内部组件col列表
          type: Array,
          default: {}
        },
        form: { // 组件绑定值列表
          type: Object,
          default: {}
        }
      },
      methods: {
        isObject (obj) {
          return typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Object]'
        },
        getSlotComponent (slot) {
          let child = _ => {
            let tag = slot.tag
            let key = slot.key
            return this.getComponent(tag, key, slot)
          }
          return child
        },
        // 处理内部的slot
        genScopedSlots (slots = {}) {
          let scopedSlots = {}
          let child
          Object.keys(slots).map(key => {
            let slot = slots[key]
            child = this.getSlotComponent(slot)
            scopedSlots[key] = child
          })
          return scopedSlots
        },
        initSpecialProps (props, obj) {
          let { disabled, text, click, name } = obj
          if (!props.props) props.props = {}
          if (!props.domProps) props.domProps = {}
          if (!props.on) props.on = {}
          if (!props.attrs) props.attrs = {}
          if (text) props.domProps.innerHTML = text
          if (click) props.on.click = click
          if (disabled) props.props.disabled = disabled
          if (name) props.attrs.name = name
        },
        getElButton (tag, slot = {}, props) {
          let h = this.$createElement
          if (tag === 'el-button') {
            if (slot.options) {
              return slot.options.map(item => {
                let itemProps = this.initProps(item)
                return h(tag, {
                  ...itemProps,
                  domProps: {
                    innerHTML: item.text
                  },
                  props: {
                    type: item.type
                  },
                  on: {
                    click: item.click
                  }
                })
              })
            } else {
              return h(tag, props)
            }
          }
        },
        getComponent (tag, key, slot = {}) {
          let h = this.$createElement
          let props = this.initProps(slot, key)
          this.initSpecialProps(props, slot)
          if (tag === 'el-select') {
            let child = slot.options.map(item => {
              return h('el-option', {
                props: {
                  label: item.label,
                  value: item.value
                }
              })
            })
            return h(tag, props, child)
          } else if (tag === 'el-input') {
            if (slot.disabled) props.domProps = slot.disabled
            return h(tag, props)
          } else if (tag === 'el-button') {
            return this.getElButton(tag, slot, props)
          } else if (tag) {
            return h(tag, props)
          } else {
            let text = slot.text || this.form[slot.key]
            if (slot.formatter) text = slot.formatter(text)
            return h('span', text)
          }
        },
        // 初始化props
        initProps (obj, key) {
          let opts = {
            ...obj
          }
          let keys = ['class', 'style', 'attrs', 'props', 'domProps', 'on', 'nativeOn', 'directives', 'key', 'slot', 'ref', 'refInfor']
          keys.forEach(key => {
            if (obj[key]) opts[key] = obj[key]
          })
          let vm = this
          // 双向绑定
          if (key) {
            if (!opts.domProps) opts.domProps = {}
            if (!opts.on) opts.on = {}
            if (!opts.props) opts.props = {}
            opts.props.value = this.form[key]
            opts.domProps.value = this.form[key]
            opts.on.input = function (value) {
              vm.form[key] = value
            }
          }
          if (obj.slots) {
            opts.scopedSlots = this.genScopedSlots(obj.slots)
          }
          return opts
        }
      },
      render (h) {
        let slots = this.cols.slots
        let innerBox = slots.default.map(col => {
          let colProps = {
            prop: col.prop,
            label: col.label
          }
          col.props = {
            ...(col.props || {}),
            ...colProps
          }
          return this.getComponent(col.tag, col.key, col)
        })
        let wrapperTag = this.cols.tag
        let wrapper = h(wrapperTag, {
          props: this.cols.props
        }, innerBox)
        return wrapper
      }
    }
    

    相关文章

      网友评论

          本文标题:Vue自定义组件

          本文链接:https://www.haomeiwen.com/subject/skngbltx.html