可视化编辑工具开发回顾 part1 - 基本配置

2020-02-21#CODING

在公司内部的可视化页面编辑工具运行了挺久了,这么长的时间里,趁着开发的感悟仍在,又看到了这个工具在内部造成的影响,写下这一篇记录吧。

可能东西比较多,篇幅较长,那就分成一个部分一篇吧。这是第一篇,关于基本配置的。

配置结构

在没接触过这类工具之前,感觉很复杂,现在回头看,感觉剥皮抽骨之后,其中核心,其实是一份配置。图形界面上的所有操作,都是在编辑这份配置。最后产出的也是根据这份配置生成的代码。

虽然只是一份配置,其结构设计又是很重要,打好了基础,就可以走的更远。而现有的这份配置很简单,就是一份扁平的 key, value,key 是组件 id,value 就是组件的各种数据。为了直观,配置的格式可简化为这样:

1{ 2 "instance_id_1": { 3 "key": "instance_id_1", 4 "componentName": "", 5 "slots": { // 父子关系 6 7 } 8 "data": { 9 "propsData": {}, 10 "style": {} 11 } 12 }, 13 "instance_id_2": {} // 另一个组件的结构 14} 15

需要说明的是**,目前我们的做法是以 vue 为基础,vue component 作为一个配置的节点,**所以上面的 instance_id_1 就是代表一个 vue component 的配置。

很容易看到, slots, propsData 这些关键词,代表着父子嵌套、属性传递这些功能。即一个页面其实是由各种 vue component 组成 ,他们会有嵌套、事件通信、属性传入。

嵌套

注意看上面的 slots 字段,这个字段到最后可能是这样的形态:

1"slots": { 2 "default": ["children_instance_key_1", "children_instance_key_2"], 3 "footer": ["children_instance_key_3"] 4} 5

在 vue.js 里有一个概念叫 Named Slot ,所谓 slot 就是一个个插槽。这份配置的意思就是描述了在哪些插槽放置哪些子组件这个关系。这解决了嵌套问题。

属性传入

负责属性传入的是 **propsData,**propsData 下的属性多是静态属性,比如 margin-left,margin-right 之类的。这些属性最后都会固化到 vue 的模板上,大概长这个样子:

1<MyComponent :marginLeft="30" :marginRight="40" /> 2

事件通信

事件也是基于 propsData 去实现。在这次项目里的事件通信的范围是同一个页面里面的 component。只是简单的点对点、点对多点、多点对一点的触发和监听,比较简单的事件机制。

看一个例子,假设有 2 个 comp,如下:

1<CompA key="comp_a" :listener="['comp_b']" /> 2<CompB key="comp_b" :trigger="['comp_a']" /> 3

这三个组件传入了 listener 这个属性,在组件里,它们大概是这样写的:

1// CompA 2import { triggerEvent } from 'sdk' 3 4export default { 5 mounted () { 6 triggerEvent("a_event_type", this.listener, {msg: 'hello'}) 7 } 8} 9 10// CompB 11import { onEvent } from 'sdk' 12 13export default { 14 mounted () { 15 onEvent("a_event_type", this, function (data) { 16 console.log(data.msg) // => hello 17 }) 18 } 19} 20

这里的代码示例出现了 **sdk,**它是用于开发组件的一套工具库,这个后面再说。

从示例来看,用户通过图形界面去标记哪些组件该监听哪个组件的事件,编辑器会把关系记录下来。等组件的逻辑在 runtime 运行起来时,通过传入属性值到 triggerEvent 里,就能知道事件触发的目标是哪些组件了。

在监听事件的时候,onEvent 传入 this,即传入 vue 的组件实例,这样事件触发时,也能知道自己该不该接收到这个事件了。

总结来说,sdk 内部维护一份映射关系,统一管理事件的监听和触发。

但这样的缺点也很明显,接收者不知道自己将会接收到什么样的 data,不知道是 string 还是 number,如果是 object,也不知道结构是怎样的。目前的做法是,在开发组件时,只处理本组件需要的数据,如果数据类型和结构不符合,忽略就好。

最后

配置是扁平的,但是里面的 slots 记录了父子关系,到最后生成代码的时候,扁平的配置会变成嵌套的 vue component html 模板。

propsData 里的数据,也会写到每个 vue component 的 上面。

除了属性,propsData 还承担了 event 触发者和监听者的记录功能。除了在 propsData 里记录,sdk 里面也会维护一份映射,并统一管理事件的触发和监听。

至此,这份配置的功能是什么,以及如何据其得出一个页面的,大致流程就是这样了。

可是用户该以何种交互方式来修改这些配置?sdk 这个开发工具库里需要提供什么,才能更方便的开发组件?前者涉及到状态的管理和交互的开发,后者涉及到了可视化工具的组件接入。这些都是后面继续要去讨论的。

🩷
0
👍
0
😄
0
🙁
0