前面说到我们可以通过面板配置来更新画布上面的一些属性,如果我们有这样一个需求:在右侧面板配置里面需要查看字体的样式效果我们应该怎么做呢?
我们一开始字体的渲染:
const fontFamilyArr = [
{
value: '"SimSun","STSong',
text: '宋体'
},
{
value: '"SimHei","STHeiti',
text: '黑体'
},
{
value: '"KaiTi","STKaiti',
text: '楷体'
},
{
value: '"FangSong","STFangsong',
text: '仿宋'
}
]
fontFamily: {
component: 'a-select',
subComponent: 'a-select-option',
text: '字体',
options: [
{
value: '',
text: '无'
},
...fontFamilyArr
],
afterTransform: (e: any) => e
},
后面改成:
const fontFamilyOptions = fontFamilyArr.map((font) => {
return {
value: font.value,
// 第一种写法生成vnode
text: h('span', { style: { fontFamily: font.value } }, font.text)
// 使用:tsx写法,需要把文件后缀名改成tsx
text: <span style={{ fontFamily: font.value}}>{font.text }</span> as VNode
}
})
options: [
{
value: '',
text: '无'
},
...fontFamilyOptions
],
渲染的时候有两种方案:方案一使用tsx进行渲染,方案二:借助render函数桥梁,将vnode转换成真实dom
方案一:使用jsx重写组件sfc写法 Single File Component写法,jsx文件天生就是转换vnode
jsx动态组件名称
在jsx中对于动态组件名称,我们必须要拿到其实例,然后把一个变量赋值给组件实例
import { Button } from 'button'
const Name = Button
<Name />
展开属性
<Component {...props} />
事件写法
v-on:click => onClick
第一种使用tsx渲染:将PropTable.vue文件改成PropTable.tsx文件,返回的是dom,
import { Input, InputNumber, Slider, Radio, Select} from 'ant-design-vue'
// jsx对于动态组件,我们必须要拿到其实例,再把一个变量赋值给组件实例,所以我们要解构出组件实例。
const mapToComponent = {
'a-input': Input,
'a-textarea': Input.TextArea,
'a-input-number': InputNumber,
'a-slider': Slider,
'a-radio-group': Radio,
'a-radio-button': Radio.Button,
'a-select': Select,
'a-select-option': Select.Option
} as any
return () => (<div class="props-table">
{
Object.keys(finalProps.value).map(key => {
const value = finalProps.value[key]
const ComponentName = mapToComponent[value.component]
const SubComponent = value.subComponent ? mapToComponent[value.subComponent] : null
const props = {
[value.valueProp]: value.value,
...value.extraProps,
...value.events
}
return (
<div key={key} class="prop-item">
{ value.text && <span class="label">{value.text}</span>}
<div class="prop-component">
{/* 渲染动态组件名 */}
<ComponentName {...props}>
{value.options && value.options.map(option => {
return (
<SubComponent value={option.value}>{option.text}</SubComponent>
)
})}
</ComponentName>
</div>
</div>
)
})
}
</div>)
finalProps:
方案二:使用render函数实现桥梁
// RenderVnode.ts
import { defineComponent } from 'vue'
const RenderVnode = defineComponent({
props: {
vNode: {
type: [Object, String],
required: true
}
},
render() {
return this.vNode;
}
})
export default RenderVnode
在propsTable中使用
<template v-if="value.options">
<component
:is="value.subComponent"
v-for="(option, k) in value.options"
:key="key"
:value="value.value"
>
<!-- {{ option.text }} -->
<render-vnode :vNode="option.text"></render-vnode>
</component>
</template>