手撸低代码平台搭建(三)组件间交互的实现

10,796 阅读6分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

前言

大家好,我是多肉攻城狮,我们在上一篇文章中主要介绍了低代码平台的页面设计器相关的一些功能原理,打通了页面设计器顶部操作栏、左侧组件列表,中间画布、右侧属性配置四个部分的关系。能够实现组件列表的展示、组件到画布的拖动,属性配置修改对组件渲染效果影响,并说明了页面设计器中设计好的页面是如何进行渲染的。

虽然我们看起来实现了通过组件拖拉拽完成页面的开发,但是目前的页面还是无法进行使用的,这是因为页面中的组件都是相互独立而又没有关联的。实际页面中的绝大多数组件都需要进行相互通讯。例如当我们点击某个按钮时,需要获取到表单组件的表单值进行提交;又比如我们点击某个按钮会弹出一个弹窗。我们这一篇文章将重点分析一下在低代码开发中组件间交 互的实现方式。

事件

事件的分类

我们主要依托于事件来进行组件间的交互。为了满足组件与组件、组件与系统、组件与服务端的交互,我们大致可以将事件分为三个类别:

  1. 组件方法:每个组件都会暴露出一些方法供其他组件进行调用。例如表格组件,我们可以暴露出查询表格数据方法;弹窗组件,可以暴露打开、关闭方法等等。
  2. 系统动作:有些方法并不属于某个组件,而是系统全局的动作,例如路由的跳转、全局的消息提示、页面加载动画的显隐等等。-
  3. API调用:这一类主要用于处理组件与服务端的交互,也就是服务端api接口的调用。

事件的定义

系统动作和API调用的定义相对比较简单,我们可以在vue组件的methods中进行方法的定义,例如我们可以定义一个request方法用于api的调用,request中调用了我们使用axios封装好的统一的请求方法,request方法支持传入apiurlmethodapi参数等信息。这两类事件为全局事件,我们可以将这些方法放到mixins中,然后在各个组件中进行引用。

而对于组件方法,我们需要将组件暴露的方法定义在各个组件的methods中,并在组件加载时进行方法的监听。

window.vm.$on(`${id}-${methodName}`, params => {
  // TODO
})

在组件销毁时取消监听。

window.vm.$off(`${id}-${methodName}`)

还记得吗,我们在上一篇文章页面设计器设计好页面时,生成的组件元数据项中附加了一个id字段,而这个字段在事件监听中也起到了重要作用,能够有效的避免页面中相同的组件重复的触发事件。

做好事件的监听后,我们就可以使用emit关键字触发事件了。

componentMethod(id, methodName, params) {
  window.vm.$emit(`${id}-${methodName}`, params);
}

在事件配置的时候只需要调用methods中的componentMethod方法就可以了。

事件的配置

上一篇文章中我们讲到,设计器中的每个组件都对应了一段json元数据,我们某个组件的属性时,会到设计器属性配置区域进行表单值的修改,从而修改整个页面json中该组件所对应的这一段json,同理,当我们进行某个组件的事件配置时,也会对组件的事件属性进行赋值,我们将这个事件属性定义为event。属性值为一段js函数字符串,如下图所示。

image.png

这样,我们执行事件时,只需要将函数字符串转换为函数进行调用就可以了。

对于代码编辑器插件,推荐一下ace,相对比较成熟,功能丰富,上手简单。这里我们就不做详细的介绍了,有兴趣的小伙伴可以到ace官网查看。

image.png

事件的执行

上面讲到,我们将事件配置成了一段函数字符串,那如何来执行呢,相对对于小伙伴来说并不难,我们可以使用eval或者Function去执行,这里我们选择使用Function

首先我们定义一个字符串函数解析方法funcStrParse

function funcStrParse(funcStr) {
  return Function("'use strict';return (" + funcStr + ")")();
}

这个方法的参数是一段函数字符串,返回值是一个函数。执行时,我们只需要调用funcStrParse返回的函数即可。

funcStrParse("这是一段函数字符串")(ctx);

眼尖的小伙伴可能发现了,我们执行这段函数时,传入了一个ctx参数,实际上,这个ctx参数就是vue组件中的this。上文中我们讲到,我们会在vue组件中的methods中定义一些系统方法(通过mixin引用)和组件方法。这样,我们在代码编辑器中编写事件时,就可以通过ctx变量调用vue组件methods中的方法了。

事件的参数

可能有些小伙伴还是有些疑问。我们已经可以通过配置去调用组件中的方法了,那么我们如何获取到其它组件中的参数呢?我们知道,组件参数的传递方式有很多,最基本的就是通过props属性或者通过project/inject进行传递。考虑到设计器中的组件繁多,并且每个组件都有独特的互不相同的组件参数,这样会导致组件标签中传递的属性过多,并且取用十分不方便。我们需要将各个组件暴露的参数放到一个公共的地方,这样在使用的时候就非常方便了。这个公共的地方定义到vuex中的store中还是比较合适的。我们以页面为单位注册storemodule,将所有的组件变量都存到所在页面modulestatepageParams对象变量中。如下图所示。其中id就是组件的id,也就是在pageParams变量中,我们以组件的idkey,以组件的参数集合对象为value。这样,我们就可以直接在事件配置中进行使用了。

image.png

后记

页面设计器中如何实现组件间的交互,我们就分享完啦。小伙伴们有没有更好的实现方式呢?欢迎评论交流。在后面面的章节中,我们会介绍一下当页面设计器中提供的组件不足以支撑我们的页面设计时,我们是否能够通过自定义组件的方式来补充左侧的组件列表,拖拽到画布中,实现我们的需求呢?感兴趣的小伙伴可以关注一波啦!