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

实现组件拖拽功能

目标

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

个人最终实现效果:

代码

拖拽功能代码

备注:使用了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个模块,组件库,编辑器,配置类。刚好对应着页面的左中右。

相关推荐
GIS开发特训营6 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood32 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.10 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
2401_8576009513 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_8576009513 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL13 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
轻口味13 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js
2402_8575834913 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
java_heartLake14 小时前
Vue3之性能优化
javascript·vue.js·性能优化