使用
schema轉爲對應的button渲染出來。
輸入:schema
輸出:button Vue組件
核心過程:schema經過渲染引擎解析成button渲染器。
語法:tsx(與jsx類似)
schema
{
"label": "編輯 Button",
"type": "button",
"actionType": "dialog",
"className": "m-l-md",
"showAsLabel": false,
"level": "success",
"size": "large",
"loading": false,
"icon": "mtdicon-cart",
"tooltip": "11111",
"tooltipPlacement": "top",
"tooltipTrigger": "hover",
"dialog": {
"title": "編輯",
"body": [
{
"type": "tpl",
"tpl": "1111"
}
]
}
}
源碼實現步驟
渲染器的使用
// 調用渲染引擎
<Render :schema="schema"></Render>
import { Render } from '../../src/index';
../../src/index.ts
// 首先,初始化各渲染器,即執行步驟一到步驟四。
import './renderers';
// 其次,調用渲染器引擎,解析schema映射到對應的(Button)渲染器。即步驟五
import {
Render,
customRegistRenderer,
} from './engine';
步驟一 定義button組件
/*
** 引入Button組件
*/
import './renderers';
renderers.ts
import Button from './Button';
export default {
Button,
}
/*
** 定義Button組件
*/
export class Button extends Vue.Component<any> {
...
render() {
<mtd-button
{...{props}}
class={className}
type={level}
htmlType='button'
onClick={this.handleAction}
>
{label || text}
</mtd-button>
}
}
步驟二 執行註冊Button渲染器
Button渲染器繼承自Button基本組件。較Button組件擴展了些通用屬性方法。
/*
** 調用@registerRenderer裝飾器,註冊Button組件爲一個渲染器(ButtonRenderer)
** 調用@WithExpression裝飾器,擴展ButtonRenderer功能(高階組件HOC)
*/
@registRenderer({
name: 'button', // 唯一標識
test: (path: string, config: any) => { // schema匹配時用到
return Boolean(/\/(?:action|button)$/.test(path) || ~['button', 'reset', 'cancel'].indexOf(config.type));
},
filter: (config: any, path: string, props: any) => ({
disabled: config.hasOwnProperty('disabled') ? config.disabled : props.disabled,
}),
})
@WithExpression
export default class ButtonRenderer extends Button {}
步驟三 實現註冊渲染器的方法
/*
** @registRenderer
*/
export const registRenderer = (config: RendererConfig, storeFactory?: any) => (Component: any) => {
if (!config.name || !config.test) {
throw new Error('模型註冊格式錯誤');
}
if (~rendererNames.indexOf(config.name)) {
throw new Error(`${config.name} 已經註冊了, 不能重複註冊`);
}
const rendererName = config.name; // 'button'
let composeComponent = Component; // ButtonRenderer
// 注入通用邏輯 可忽略
composeComponent = withCommonLogic(composeComponent);
config.Renderer = composeComponent;
rendererNames.push(rendererName); // 暫存爲已註冊渲染器
rendererConfigSet.push(config); // 暫存config: {name: 'button', test: *, Renderer: composeComponent}
return Component;
};
步驟四 實現高階擴展渲染器的方法
/*
** @WithExpression
*/
擴展項包括除props、render、click函數handleAction外的所有:
name、props、data、methods、生命週期函數(created、mounted、beforeUpdate、updated、render),
其中render中調用(Button)渲染器組件,並傳遞格式化好的prop屬性。
使用高階組件方法
// 擴展並返回擴展後的Button渲染器組件,ComposedComponent爲渲染器組件,OnExpression爲擴展屬性
return createHOC(ComposedComponent, OnExpression);
步驟五 渲染器引擎
engine/Render.tsx
/**
** 作用是找到對應的渲染器模型,並調用渲染。
**/
const rendererConfig = getRenderer(path, schema);
const renderer = rendererConfig.Renderer;
// 利用path從步驟三中的rendererConfigSet中查找出對應渲染模型
return (
<renderer {...rendererConf}>
</renderer>
);
// 渲染出組件