自己动手设计一个表单设计器?低代码平台?

2,606 阅读3分钟

变速直线运动的速度是位置函数对时间的导数,加速度是速度对时间的变化率。

关于低代码平台

低代码平台顾名思义,在开发过程中尽量减少开发人员需要写的代码的数量。对于前端来讲,表现形式主要为配置化拖拽的形式。

这里聊一下个人对拖拽式的一些理解。

页面布局及数据流

通常这些拖拽式的低代码开发平台,布局样式如下:

左侧部分为组件,中间是内容展示区域,组件拖拽过来会展示在内容区域,右侧为参数配置区域,可以在右侧为组件配置对应的参数。

上图最左侧部分定义为Setters,用来封装组件可能接受的参数,其最终表现是最右侧灰色部分的表单。这个部分是可有可无的,业务组件也可以直接接受参数,在最右侧展示参数表单进行配置。

根据之前的开发经验,数据的流程预计如下图:

参数==>Setter==>业务组件==>更新展示内容

当然也有可能不需要Setters,直接:

参数==>业务组件==>更新展示内容

当然,肯定还需要一个全局的对象来操作这些个数据流。

实现拖拽展示组件

这个操作的目的是将左侧展示的业务组件拖拽到内容展示区让它能够正常展示。

左侧的组件列表比较容易实现。将写好的组件导出一个数组然后遍历,只展示组件名称就可以。

 <DarggableComponent
    v-for="item in componentList"
    :key="item"
    :itemInfo="item"
/>

拖拽组件的实现

如果只是简单的实现这个拖拽功能,去下载一个别的包岂不是有点麻烦了?直接用dragAPI整呗。

DarggableComponent.vue

<template>
  <div class="draggable-item" draggable="true">{{ itemInfo.name }}</div>
</template>
<script>
import Vue from 'vue'
export default {
  setup() {},
  props: {
    itemInfo: Object,
  },
  data() {
    return {}
  },
  mounted() {
    console.log(this.$store)
    // let dragged
    let self = this
    /* 拖动目标元素时触发drag事件 */
    document.addEventListener(
      'drag',
      function() {
        // console.log(event)
      },
      false
    )

    document.addEventListener(
      'dragstart',
      function(event) {
        // 保存拖动元素的引用(ref.)
        // dragged = event.target
        // 使其半透明
        event.target.style.opacity = 0.5
      },
      false
    )

    document.addEventListener(
      'dragend',
      function(event) {
        // 重置透明度
        event.target.style.opacity = ''
      },
      false
    )

    /* 放置目标元素时触发事件 */
    document.addEventListener(
      'dragover',
      function(event) {
        // 阻止默认动作以启用drop
        event.preventDefault()
        // event.target.style.background = 'purple'
      },
      false
    )

    document.addEventListener(
      'dragenter',
      function(event) {
        // 当可拖动的元素进入可放置的目标时高亮目标节点
        if (event.target.className == 'contents') {
          // event.target.style.background = 'purple'
        }
      },
      false
    )

    document.addEventListener(
      'dragleave',
      function(event) {
        // 当拖动元素离开可放置目标节点,重置其背景
        if (event.target.className == 'contents') {
          event.target.style.background = ''
        }
      },
      false
    )

    document.addEventListener(
      'drop',
      function(event) {
        // 阻止默认动作(如打开一些元素的链接)
        event.preventDefault()
        // 将拖动的元素到所选择的放置目标节点中
        if (event.target.className == 'contents') {
          self.$store.commit('setRenderedComponents', self.itemInfo)
          Vue.component(self.itemInfo.key, self.itemInfo.component)
        }
      },
      false
    )
  },
}
</script>
<style>
.draggable-item {
  background: red;
  border: 5px solid green;
}
</style>

拖拽完成后如何展示组件

路由中配置组件?异步组件?render函数?直接在页面中导入组件?似乎都不合适。

我们的需求是动态注册这个组件,拖拽完成后能够在内容区域正常展示。思考后以后,采用了Vue.component这个方法,在拖拽完成后直接将我们的组件注册为全局组件,同时全局缓存一个需要渲染的组件列表。

这样我们就可以在拖拽完成后直接看到渲染结果。

document.addEventListener(
      'drop',
      function(event) {
        // 阻止默认动作(如打开一些元素的链接)
        event.preventDefault()
        // 将拖动的元素到所选择的放置目标节点中
        if (event.target.className == 'contents') {
          self.$store.commit('setRenderedComponents', self.itemInfo)
          Vue.component(self.itemInfo.key, self.itemInfo.component)
        }
      },
      false
    )

在内容展示区如何展示组件

测试了render函数以及其他方法都不行以后。忽然想到Vue有一个全局的component组件,直接用这个就行了。

<div v-for="item in renderedComponents" :key="item">
  <component :is="item.key"></component>
</div>

然后就可以实现如下功能了:

从左侧组件中拖拽组件到内容展示区,组件组渲染为正常的组件内容

总结

表单编辑器这一类的东西有很多,但是自己没有想过去实现一个,既然之前用过,不妨仔细思考一下其中的流程,找时间自己去实现一个简单的。

接下来的任务是将数据流打通,让内容区域实现可配置化。

最后说两句

  1. 动一动您发财的小手,「点个赞吧」
  2. 动一动您发财的小手,「点个在看」
  3. 都看到这里了,不妨 「加个关注」
  4. 不妨 「转发一下」,好东西要记得分享