AMIS实现渲染一个button的源码分析-Vue
使用schema转为对应的button渲染出来。输入:schema输出:button Vue组件核心过程:schema经过渲染引擎解析成button渲染器。语法:tsx(与jsx类似)schema{"label": "编辑 Button","type": "button","actionType": "dialog","className": "m-l-md"...
·
使用
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>
);
// 渲染出组件
更多推荐
已为社区贡献6条内容
所有评论(0)