基于vue component 特性实现逻辑复用

117 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情 >>

在我们的业务开发过程中,经常会遇到这样的场景,我们以OMS 订单管理系统为例,经常会有联查下游单据,参照选择其他业务单据,动态关联其他业务单据这样的情况,常见的,我们的实现可能是下面这样的

  • 各业务单据具有各业务单据的路由,并各自对应各自的视图组件
  • 将列表部分提取为组件,只包含数据展示,数据处理,不包含数据拉取
  • 需要弹窗参照或动态关联时,在需要关联的地方重复调用对应业务接口,传入列表组件进行选择

这样做的好处是什么?各自业务可以灵活的处理自己的需求,列表组件不包含业务状态,仅进行数据展示;

那么他的弊端是什么呢?重复的业务逻辑需要不断在各个地方进行 ctrl +c & ctrl +v,造成大量的代码像满天星一样散落在各处,假如业务有调整,那需要一次修改各个地方的调用,因为是在其他业务内通过接口调用,业务本身并不知道有多少在调用他,很容易出现漏改代码的情况,造成大量的工作量

基于以上的一些痛点,我在新的ETMS平台上尝试采用了参数路由+component抽象组件的方式进行动态引用,其他业务在引用当前业务时,依赖的就是当前业务本身所提供的能力,通过配置出入参的方式进行查询条件预置与选择参数的导出,非常灵活,而且因为依赖的就是当前业务,当业务有变动的时候,很容易就可以实现更新兼容

实现

  • 路由设计上,采用了参数路由与静态路由相结合的方式,整个项目的流转都基于定义好的参数路由 moduleCode

/view/:moduleCode/:moduleType

moduleType则是为了标识是列表还是详情,这个决定了我们functionCode所绑定的模版的拉取条件

  • 页面上,采用vue 抽象组件 component 来进行组件加载, 通过moduleCode+moduleType拉取到的模版内会标识由哪个组件来进行解析我们的模版
// 动态解析模版
<template>
  <component
    :module-code="moduleCode"
    :module-type="moduleType"
    :is="moduleType"
  />
</template>

<script>
import List from 'components/analysis/list.vue'
import Form from 'components/analysis/form.vue'
  • 而列表模版又会基于模版内返回的类型继续进行拆分,这里是我的业务设计,你们可以直接在List这一层就做数据模版的绑定也没问题
 <component
    ref="component"
    :module-code="moduleCode"
    :temp="temp"
    :is="LayoutType"
    :is-modal="isModal"
    :search-params="searchParams"
    :is-multiple="multiple"
  />

这里我们依然采用了动态路由,并将模版传入,注意看传入的props,isModal是标识是否是被弹窗所引用而渲染的,searchParams是动态入参,isMultiple决定了我们的列表是单选还是多选

  • 接下来就是引用弹窗
 <List
  :module-code="referModuleCode"
  module-type="List"
  :is-modal="true"
  ref="List"
  :search-params="inParams"
  :multiple="multiple"
/>

直接在页面内引入List组件,传入对应业务的moduleCode,searchParams,isMultiple等属性,这样就在当前业务内通过弹窗的方式加载了其他业务的页面

  • 业务内需要提供的能力
getCheckedRow () {
  return this.$refs.xTable.getCheckboxRecords(true)
},
getRadioRow () {
  return this.$refs.xTable.getRadioRecord()
},

业务内当然是需要提供获取单选与多选的列表的方法,然后在List组件内进行调用

getRefCheckData () {
      return this.multiple ? this.$refs.component.getCheckedRow() : [this.$refs.component.getRadioRow()]
    },

注意看我在List内针对获取数据做了一层包装,无需在最外层获取数据时进行判断,我在这里就已经将数据都包装为了数组格式,其他业务在引用时只需要调用统一的getRefCheckData方法即可获取,无需关心是单选还是多选,返回值是对象还是数组

结语

通过这样的方式,我们就实现了逻辑复用,避免了多次配置弹窗相关属性,而且弹窗能力完全依赖各自业务的实现,业务越强,弹窗越强!