t6s前端架构-bus总线事件

bus事件总线

顾名思义,就是事件(函数的)公交车,对于vue组件开发,有什么好处呢

其实就是方便组件之间通信,用js的一等公民函数

比如,2个组件

1、接口树列表(包含接口分组,接口数据)

//接口树组件 js
//注册事件,当脚本变化更新(非空)接口脚本字段
bus.$on(bus.msg.onSaveLinkScript,()=>{
  const {id,script} = vars.link
  script && api.saveLink({id, script})
})
...
//执行事件 
bus.$emit(bus.msg.initLinkScript,node.script)

 

2、脚本编辑(依赖接口数据,随之变化,反之脚本更新需要更新接口数据)

//脚本编辑器 js
//注册事件,初始化脚本编辑器内容
bus.$on(bus.msg.initLinkScript,(script)=>{
  editorInstance?.setValue(script || "return 'welcome t6s'")
})
...
//执行事件,脚本更新,立即更新接口
editorInstance.onDidChangeModelContent(() => {
  bus.$emit(bus.msg.onChangeEditLinkScript,editorInstance.getValue())
  doValidate()
})

 

用事件驱动比,对象数据传递的好处,我感觉不会污染数据

数据都是本组件内部变量,不会在其他地方改变,

即便被修改,也是定义在组件内部的bus事件,有理有据,架构清晰

bus架构,简化版本

bus.js我的设计很简单,重在高效,不需要的功能,剔除

比如,我主要解决组件之间通信,bus就是函数集合,所有只需要注册,用的时候调用即可

那么,就不需要注销,注销没有意义,一旦注册,就是必须要使用的

先看一下,理解一下,bus.js


const fns = {}

const $on = (name,fn)=>{//相同消息,事件函数字符串,注意别重复
    fns[name] = fns[name] || []
    fns[name] = fns[name].filter(it => it.toString() !== fn.toString()) //通过脚本字符串对比,过滤过期事件
    fns[name].push(fn)
}

const $emit =  function (name){
    fns[name]?.forEach( (fn)=>{
        fn.apply(this,Array.from(arguments).slice(1))
    })
}
export default {
    $on,
    $emit,
    msg:{
        loadCaseList:'加载用例列表',
        updateFlowCount:'更新用例流程数量',
        initLinkScript:'初始化接口脚本',
        onChangeEditLinkScript:'脚本编辑实时更新',
        updateRunLinkResult:'更新接口运行数据',
        onSaveLinkScript:'保存接口脚本',
        onRunLinkScript:'运行接口脚本'
    }
}

 

精髓

看完之后,可能会有疑问,为啥同名同参数事件函数会有多个,每次emit执行也是批量

这里就是为啥定义bus,而不使用直接定义单纯单个函数(不实现,用的时候实现)

批量注册批量执行才是bus的精髓

假如,有3个组件

1、数据组件

2、曲线展示组件

3、柱状图展示组件

如果组件1,数据变化,需要更新 2和3组件,就需要再2 3组件内部定义相同事件(名称相同)实现不同(需要改变各自组件内部对应值)

当然,有人会说可以用,父组件给子组件传递值,要维护这种关系代价很大,非常影响架构设计

我的架构中,基本不用父子传递数据,和Vue3依赖注入:provide和inject(非父子关系数据传递)

 管理起来非常麻烦,代码层次较为复杂,不清晰

还是要组件内部数据,自己管理好稳妥些

 

坑点

事件名称与函数相同事件,被判定过期事件

为何要判断过期,因为组件在挂载销毁时,变量都会重新初始化,而bus事件引用了过期变量,所以要重新注册,并且需要过滤掉过期事件函数(bus是全局的,不会随组件销毁而失效,需要手动过滤)

例子:

//两个方法都是一样的,必须把变量传递修改下,让字符串不相等,否则,只会有一个生效
//fns[name] = fns[name].filter(it => it.toString() !== fn.toString()) //过滤过期事件
//LinkArgsList.vue
bus.on(bus.msg.linkEditorArgsPanelHighChange,(h)=>{
    const height = h-122.2
    vars.scrollHeight = height+'px'
  })

//LinkArgs.vue 
  bus.on(bus.msg.linkEditorArgsPanelHighChange,(height)=>{
    height = height-122.2
    vars.scrollHeight = height+'px'
  })

 

posted @ 2024-08-14 10:29  tssssss|t6s  阅读(76)  评论(0)    收藏  举报