手把手带你开发一个低代码可视化平台(一)硬核架构教程,全程开源同步开发

10,090 阅读3分钟

起因

我在月初开源的商城零代码可视化搭建平台Mall-Cook受到大家喜爱,使我深受鼓励,谢谢大佬们的支持。本着授人以鱼不如授人以渔思想,决定在项目新建shelf分支,从零开发一个"干净"的可视化搭建平台,带大家开发一个自己的可视化搭建平台。

商城可视化搭建平台  Mall-Cook

可视化搭建核心

架构

先看一下我理解的无代码可视化搭建平台架构,可视化搭建平台主要有两块:

  • 项目拖拽搭建平台的构建
  • 物料接入平台流水线的构建

可视化搭建平台架构

核心

可视化搭建的核心是什么?

开发搭建平台使我们搭起了可视化构建的架子,接下来只需要根据实际使用场景更新物料库"运营"平台。 而在更新物料库时(老物料的迭代与新物料的开发),我们也需要同步修改平台来兼容物料库。那怎么解决这个问题呢?

我的解决办法是,利用Json Schema协议规范Json的作用,用规范的Json来描述物料,然后用物料属性解析器来解析、构造物料的属性面板,我们更新物料库时只需要修改对应Json即可。最后提供Schema生成器可视化生成Json,避免用户手动修改Json,完成一整条物料接入平台流水线的构建。

这时我们再回到问题,我认为可视化搭建的核心是一套规范

在平台中我们利用Schema协议定义了物料属性规范,然后遵循规范构建一条标准接入的流水线。我们在开发同理可以定义其他规范,完成组件交互页面生命周期远程接口调用等标准流水线(此平台为无代码平台,开发低代码平台需要上述功能)。

画虎画皮难画骨,我认为这才是可视化搭建的难点!

开发拖拽搭建面板

我们使用的拖拽插件是vuedraggable,主要逻辑为拖拽模板物料到页面面板,深拷贝物料配置数据到页面配置中。

核心代码

  <!-- 物料模板列表 -->
  <draggable
    v-model="widgets"          // 拖拽列表数据源
    :options="{ 
      group:{ 
              name: 'itxst',   // 可拖拽列组,相同表名可相互推拽
              pull: 'clone'    // 拖拽模板物料,复制到目标列表
            }, 
            sort: false        // 是否可推拽排序
    }"  
    :clone="handleClone"       // 复制模板物料执行方法 
    animation="300"            // 动画延迟
  >
    <div
      v-for="(item, index) in widgets"
      :key="index"
      class="control-widgets-item"
    >
      <i class="iconfont" :class="item.icon"></i>
      <span class="f13">{{ item.label }}</span>
    </div>
  </draggable>
  <!-- 页面面板 -->
  <draggable
    v-model="mList"         // 拖拽列表数据源
    group="itxst"           // 可拖拽列组相同表名可相互推拽
    ghostClass="ghost"      // 拖动元素的占位样式class
    chosenClass="chosen"    // 选中目标的样式class
    selector="selector"
    :animation="500"        // 动画延迟
    :sort="true"            // 是否可推拽排序
    class="panel"
  >
    <component
      v-for="item in mList"
      :key="item.id"
      :is="item.component"
      v-bind="item"
    ></component>
  </draggable>
  // 拷贝物料模板
  handleClone(cmp) {
    return {
      ...this.$cloneDeep(model),   // 深拷贝物料模板
      id: this.$getRandomCode(8),  // 生成物料id
  },

开发可嵌套物料

想要实现可嵌套物料主要有三点:

  • 物料中包含slot,已供子物料存放
  • 物料配置中增加children属性,用于存放子物料配置
  • 递归渲染物料实现无限层级嵌套

核心代码

  <!-- 递归可嵌套组件 -->
  <draggable
    v-model="list"
    group="itxst"
    ghostClass="ghost"
    chosenClass="chosen"
    selector="selector"
    :animation="500"
    :sort="true"
    :class="[isWidget ? 'nest-child' : 'nest-area']"
  >
    <component
      v-for="item in list"
      :key="item.id"
      :is="item.component"
      v-bind="item"
    >
      // 包含slot的组件才能进行嵌套渲染
      <ControlNestWidget
        :widgets.sync="item.children"   // 子物料列表
        :isWidget="true"                // 是否为子物料
      ></ControlNestWidget>
    </component>
  </draggable>

开发物料容器

接下来我们为页面的物料加一个保姆工具栏,使用容器组件可以解耦代码功能,功能如下所示

物料容器

  <!-- 物料操作容器 -->
  <div class="shape" @click.stop="setcurComponent(widget)" ref="shape">
   
    <!-- 选中组件高亮 -->
    <div v-if="isCurComponent(widget.id)" class="shape-solid event-none"></div>

    <!-- 组件工具栏 -->
    <div v-if="show" class="shape-tab" :style="{ right: getRightStyle() }">
    
      <!-- 选中显示删除按钮 -->
      <template v-if="isCurComponent(widget.id)">
        <i
          class="iconfont icon-shanchu tab-icon f16"
          @click.stop="delComponent(chontrol.widgets, widget.id)"
        ></i>
      </template>
      
      <!-- 未选择显示物料名 -->
      <span v-else>{{ widget.label }}</span>
    </div>
    
    
    <!-- 插槽 -->
    <slot></slot>
  </div>
  <!-- 使用物料容器 -->
  <widget-shape v-for="item in list" :key="item.id" :widget="item">
    <component
      :is="item.component"
      v-bind="item"
    ></component>
  </widget-shape>

因为有嵌套组件,所以删除物料时应递归遍历删除

    // 删除物料
    delComponent(list, id) {
      // 遍历查找目标下标
      let index = list.reduce((pre, cur, i) => {
        return cur.id == id ? i : pre;
      }, -1);

      // 找到目标,删除物料
      if (index >= 0) {
        list.splice(index, 1);
      } else {
        // 递归子物料
        list
          .filter((c) => c.children)
          .forEach((c) => {
            this.delComponent(c.children, id);
          });
      }
    }

结尾

项目源码

项目代码:Mall-Cook (shelf分支)

体验地址:传送门

下一节预告

我们已经开发了可视化搭建的架子,下一节会讲述:

  • 使用json描述物料
  • 开发物料属性解析器,解析生成属性面板
  • 开发属性面板基础类型组件(string、number等)

系列文章

大家可以加群交流低代码/零代码可视化搭建