事件的分类
我们主要依托于事件来进行组件间的交互。为了满足组件与组件、组件与系统、组件与服务端的交互,我们大致可以将事件分为三个类别:
- 组件方法:每个组件都会暴露出一些方法供其他组件进行调用。例如表格组件,我们可以暴露出查询表格数据方法;弹窗组件,可以暴露打开、关闭方法等等。
- 系统动作:有些方法并不属于某个组件,而是系统全局的动作,例如路由的跳转、全局的消息提示、页面加载动画的显隐等等。-
- API调用:这一类主要用于处理组件与服务端的交互,也就是服务端api接口的调用。
事件的定义
系统动作和API调用的定义相对比较简单,我们可以在vue
组件的methods
中进行方法的定义,例如我们可以定义一个request
方法用于api
的调用,request
中调用了我们使用axios
封装好的统一的请求方法,request
方法支持传入api
的url
、method
、api
参数等信息。这两类事件为全局事件,我们可以将这些方法放到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
函数字符串,如下图所示。
这样,我们执行事件时,只需要将函数字符串转换为函数进行调用就可以了。
对于代码编辑器插件,推荐一下ace
,相对比较成熟,功能丰富,上手简单。这里我们就不做详细的介绍了,有兴趣的小伙伴可以到ace官网查看。
事件的执行
上面讲到,我们将事件配置成了一段函数字符串,那如何来执行呢,相对对于小伙伴来说并不难,我们可以使用eval
或者Function
去执行,这里我们选择使用Function
。
首先我们定义一个字符串函数解析方法funcStrParse
。
function funcStrParse(funcStr) {
return Function("'use strict';return (" + funcStr + ")")();
}
这个方法的参数是一段函数字符串,返回值是一个函数。执行时,我们只需要调用funcStrParse
返回的函数
眼尖的小伙伴可能发现了,我们执行这段函数时,传入了一个ctx
参数,实际上,这个ctx
参数就是vue
组件中的this
。上文中我们讲到,我们会在vue
组件中的methods
中定义一些系统方法(通过mixin引用)和组件方法。这样,我们在代码编辑器中编写事件时,就可以通过ctx
变量调用vue
组件methods
中的方法了。
事件的参数
可能有些小伙伴还是有些疑问。我们已经可以通过配置去调用组件中的方法了,那么我们如何获取到其它组件中的参数呢?我们知道,组件参数的传递方式有很多,最基本的就是通过props
属性或者通过project/inject
进行传递。考虑到设计器中的组件繁多,并且每个组件都有独特的互不相同的组件参数,这样会导致组件标签中传递的属性过多,并且取用十分不方便。我们需要将各个组件暴露的参数放到一个公共的地方,这样在使用的时候就非常方便了。这个公共的地方定义到vuex
中的store
中还是比较合适的。我们以页面为单位注册store
的module
,将所有的组件变量都存到所在页面module
中state
的pageParams
对象变量中。如下图所示。其中id
就是组件的id
,也就是在pageParams
变量中,我们以组件的id
为key
,以组件的参数集合对象为value
。这样,我们就可以直接在事件配置中进行使用了。