使用

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>
    );
// 渲染出组件

Logo

前往低代码交流专区

更多推荐