0.0.6 • Published 2 years ago

lowcode-render v0.0.6

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

Vue3 lowcode-render

Usage

入口:

<script setup lang="ts">
import { RenderEngine, EnginePropsType } from "@/components/engine";
import * as ElComponents from "element-plus";
import { addBaseFunc } from "./BaseActions";

const schema = {
  componentName: "ElButton",
  props: {
    innerText: {
      type: EnginePropsType.Model,
      value: "span",
      defaultValue: "xxxxxx",
    },
    type: "danger",
    onClick: {
      type: EnginePropsType.Action,
      actionKey: "clickTest",
    },
  },
};
</script>

<template>
  <RenderEngine
    :schema="schema"  // schema,描述页面UI及逻辑
    :components="ElComponents" // 渲染使用到的组件Map
    :add-action-func="addBaseFunc" // 自定义动作
  />
</template>

组件定义:

import * as ElComponents from "element-plus";
// 此处使用element-plus作为渲染组件库,格式{name: ComponentClass}

动作定义:

function,入参形如{getModel, setModel, remoteKey}, 返回Map{actionKey: function}

import { get } from "lodash";
import { computed } from "vue";

export function addBaseFunc({ getModel, setModel, remoteKey }: ActionFunc) {
  const router = useRouter();
  return {
    jump(params: RouterParams) { // 路由跳转动作
      router.push({
        path: params.path,
        query: params.query ?? {},
      });
    },
    toast(params: ToastParams) { // toast动作
      (ElMessage as any)[params.type]?.(params.msg);
    },
    dialog(params: DialogParams) { // Modal动作
      setModel(params.model, !getModel(params.model));
    },
    async fetch(params: FetchParams) { // 网络请求
      let customParams = {};
      if (params.fetchKey) {
        customParams = params.params ?? {};
        params = remoteKey[params.fetchKey];
      }
      const {
        url = "",
        method = "",
        params: fetchParams,
        confirmText,
      } = params;
      if (confirmText) {
        ElMessageBox.confirm(confirmText, "提示", {
          confirmButtonText: "确认发送",
        }).then(async () => {
          await sendRequest(
            url,
            method,
            [{ ...fetchParams, ...customParams }],
            params.lrMap
          );
        });
      } else {
        await sendRequest(
          url,
          method,
          [{ ...fetchParams, ...customParams }],
          params.lrMap
        );
      }
    },
    toggle() { // 添加computed追踪依赖变化
      const model = getModel("table1[0]");
      model.cateId = computed(() => `${getModel("form1.cateId")}_table`);
      setModel("condition", !getModel("condition"));
    },
    clickTest() { // 测试例子
      setModel("span", "zzzz");
    },
  };
}

整体方案

  1. 组件库,schema,Action(逻辑)分离,均支持自定义实现
  2. 使用vue3 reactive保持数据响应性,顶层数据管理,数据驱动,实现数据及数据修改和UI分离

schema定义

节点定义

interface Component {
    id?: string;
    componentName: string;
    props: {[key: string]: Props || any}; // 非Props类型时type默认为plain,节省数据开销
    condition: {}; // 渲染条件
    loop: [] || {}; // 循环数据,比如select下的options描述
    slots: {}; // 插槽
    children: Component[];
}

数据类型

无type情况下直接取值

export const EnginePropsType = {
  Plain: 'PLAIN', // 普通类型
  Model: 'MODEL', // model里面的key
  Loop: 'LOOP', // 循环绑定
  VModel: 'VMODEL', // 双向绑定
  Action: 'ACTION', // action里面的key
  Slot: 'SLOT', // JSX插槽
  SlotContext: 'SLOT_CONTEXT', // 插槽入参
  JSFunction: 'JS_FUNCTION' // 自定义函数
};

动态数据

取模型中对应的字段(key)

{
  type: EnginePropsType.Model,
  value: 'table1',
  defaultValue: []
}

循环

{
  type: EnginePropsType.Loop,
  value: 'value' // key名
}

双向绑定

VModel:比较特殊,需单独绑定,指定form和field

{
  type: EnginePropsType.VModel,
  form: 'form1',
  field: 'select'
}

Action

{
  type: EnginePropsType.Action,
  actionKey: 'reset',
  params: { sets: [{ localKey: 'table1', remoteKey: 'data.cate' }], formKey: 'form1' } // 传入action fun中的参数
}

Slot及SlotContext:

{
  slots: {
      default:
        [
          {
            componentName: 'img',
            key: '19',
            props: {
              src: {
                type: EnginePropsType.SlotContext,
                value: 'row.imgUrl'
              },
              style: {
                width: '100px'
              }
            }
          }
        ]
  }
}
0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago

0.0.0

2 years ago