从零开始搭建低代码平台(二)- 实现组件拖拽功能

实现组件拖拽功能

目标

实现组件的拖拽。 参考例子:华为低代码编辑器 阿里的编辑器也可以参考,都差不多。华为的源码开放的比较完整,所以就参考华为的了。

个人最终实现效果:

代码

拖拽功能代码

备注:使用了vue3+vite+ts+vue3DnD(拖拽库),虽然实现了功能,但非常简陋。代码量非常少,逻辑清晰很容易上手,很适合学习用和自我改造。框架也是我自己搭的,很简洁很容易上手的一个框架,也很适合自我改造。

实现的思路

个人认为思路是最重要的,思路在,方向对,一切都好说。整个功能零零散散整了快2周,若思路清晰,估计2,3天就可以整完了。我个人思路肯定有很多缺陷,仅供参考,若有大佬发现我的思路有问题,欢迎指正。

左边的组件库与右边的组件配置栏

左边组件库和右边组件配置栏,只要低代码数据规范预设好,难度不大,这两个模块代码加起来估计都不到200行,思路不清晰的小伙伴,直接看我代码即可。

中间的拖拽编辑器

  • 思路1: 样式与操作偏向于C端还是B端?

B端则是越简练越好,C端则是希望给用户有良好的交互体验。个人本来是偏向于C端的,想着这编辑器后期是可以给非技术人员用的。后面参考了其他的几个低代码平台,改为偏向于B端。

因为B端实现更容易,代码会简练清晰很多,这样扩展性和兼容性都能更强。如果要给非技术人员用,应该像钉钉宜搭那样,在阿里的低代码平台上封装多一层。低代码平台是B端,但套多一层可转换成C端,没必要把低代码平台做成C端。

  • 思路2: 拖拽器集成在一个模块(vue文件)里好,还是拆成几个好?

vue3的dnd拖拽库的示例,拖拽是分成几个模块(vue)文件的。加上平时写业务也习惯于拆分模块,这样逻辑清晰,也便于模块化。

但现实过程中,发现编辑器是要可以无限层嵌套的,实现嵌套时,拆分的多个模块会让代码变得很繁琐。最后编辑器都写在一个模块中,内部进行嵌套。最终实现效果是很好的。整个模块代码没超过200行,逻辑又很清晰。

javascript 复制代码
// 使用编辑器,SortView为编辑器,直接入参低代码数据即可,组件会自我进行嵌套。
<template>
  <div class="h-full w-full bg-[#ffffff]">
        <SortView v-bind="componentDate"></SortView>
  </div>
</template>
javascript 复制代码
// 编辑器template的核心代码片段
<template>
  <div :ref="setRef" @click.stop="clickComp" :class="{ 'inline-block': !hasChildren, 'w-full': hasChildren, }"
    class="relative">
      <component :is="componentNode" v-bind="props">
       <!-- 在这里自己进行嵌套 -->
        <sortView v-if="props.children && props.children.length > 0" v-for="item in props.children" :key="item.id"
          v-bind="item">
        </sortView>
      </component>
  </div>
</template>
  • 思路3: 编辑器里面的数据流,方向在哪里?

无论vue还是react都是单向数据流,这种方式流向清晰,利于维护和扩展。一开始我也采取这种方式,但编辑器里面的组件是可以无限嵌套的。若数据一层层往下传,又一层层的往上传,逻辑会变得繁琐,担心扩展和兼容性问题。

于是改完采用状态管理器的模式,利用vue3组合式api将低代码数据独立出来管理,懒得使用pinia了。减去注释代码,整个管理器100行代码搞定,调用比pinia更清晰。

但状态管理器有个问题,就是数据流向不清晰,当我组件想获取父组件的内容时,只能拿父组件的id从头开始遍历进行查找,性能扑街也很繁琐。本想将数据平摊开,做个数据索引,便于数据查询。但这种方式繁琐,且也没啥扩展性。因此遇到需要父级数据的情况,还是采用vue自带的inject,单向数据流的方式。

javascript 复制代码
// 获取父级的数据
const parentIsContainer = inject<any>('compParent');
//将自己的数据传输给下游
provide('compParent', { isContainer })

现在这种状态管理器+vue的Inject的方式,有些繁琐且有耦合度高,以后有时间可以进行优化。比如用类似vue实例树,把数据串起来,这样查找数据方法,也灵活很多。且也解决现在低代码数据和sortitem渲染绑定在一起了,而低代码数据是不能随意改动的,导致sortView不灵活问题。

实现

当有了上述的思路后,实现起来就容易很多了。 使用DND库模仿华为的低代码平台实现拖拽操作,我目前的编辑器属于无敌简陋版,离华为的还差"亿"点点距离。但最基础的功能是实现了的,属于毛坯房,后期再加装修就好。

不会DND的小伙伴,估计得学习一下这个库,难度其实也不高,我后期也发个DND的上手教程,帮大家快速上手。

整个拖拽功能代码量不足1000行,还分成了好几个文件,想了解的小伙伴,直接下载源码跑起来看即可。个人备注写得也是很清晰的,为了以后的扩展,逻辑也是尽量理顺了。

不信的话,看下面的例子:

javascript 复制代码
/** 当前template状态
  状态:   1.是容器但不能移动。
            当父级不是容器,自身是容器,就会这种状态。
          2.不是容器能移动
            普通组件状态。
          3.是容器也能移动
            父级是容器,本身也是容器。
            4.不能移动也不能当容器。(根节点下的内容,不能移动也不能当容器,暂时搁置先)
          备注:默认是普通组件(不是容器能移动),当父级不是容器时,子级都是不可移动的。
*/
let type: '1' | '2' | '3' = '2'
setType()
function setType() {
  const parentIsContainer = inject<any>('compParent');
  console.log('isContainer', props.componentName, isContainer, parentIsContainer?.isContainer)
  //若组件父级是容器,自身也是容器,则状态为3
  if (isContainer && parentIsContainer?.isContainer) {
    type = '3'
  }
  //若组件父级不是容器,自身也是容器,则状态为1 
  else if (isContainer) {
    type = '1'
  }
}

代码目录介绍

一共3个模块,组件库,编辑器,配置类。刚好对应着页面的左中右。

相关推荐
Bug缔造者4 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_5 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
罗政5 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
阿树梢6 小时前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写7 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js
陈小唬8 小时前
html页面整合vue2或vue3
前端·vue.js·html
花下的晚风8 小时前
Vue实用操作篇-1-第一个 Vue 程序
前端·javascript·vue.js
有颜有货9 小时前
低代码开发平台系统架构概述
低代码·系统架构
lgbisha9 小时前
828华为云征文|华为云Flexus X实例docker部署最新Appsmith社区版,搭建自己的低代码平台
低代码·docker·华为云
我是Superman丶10 小时前
【前端UI框架】VUE ElementUI 离线文档 可不联网打开
前端·vue.js·elementui