Vue自定义组件
2021-08-18 本文已影响0人
halapro_liu
使用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
}
}