vue/element表格配置化

配置化想法萌生

表格配置化主要能解决的问题就是 提高代码复用能力、提升开发效率,特别是需要开发多个大型表单系统的,配置化可以极大的提升效率,让你上班摸鱼不再是梦想!为了早点下班,我们接着往下看吧!

配置化思路其实就是对表单项进行了抽象,制定了一份协议去描述每个表单项,具体对象中的每个属性有什么用。

用配置化方式开发表单,完完全全就是为了高复用、可维护性,然后提升开发效率,解放生产力。

  1. 高复用:相似的业务逻辑进行统一处理,复用在相似领域的业务场景。如果说投放系统只需要接入一个渠道,那真的写 template 一把梭就完了。但事实上却不是这样的,当你接入了第一个 facebook ,你发现后面还有 tiktok巨量引擎广点通 等各种媒体渠道…
  2. 可维护:实现配置代替开发。即使把配置抽离,交到非技术人员处,其根据协议一样能实现表单项的增删,完成业务。并不是把东西做出来就完事了。首先,渠道方会有新配置功能推出,这个是不可控的。其次,系统开发时并不是全字段接入,而是先接入业务方所需要的核心配置,所以后期会有很多接入新的字段需求。

设计协议

首先我们思考下我们的每个表单项目需要一些什么:

  1. type 类型。比如 inputselectradio 等等
  2. label 表单项的名称/描述
  3. formKey 字段名。我们提交数据到后段的字段名,比如 form.name'name'
  4. value 存放表单值。表单上 v-model 所绑定的值
  5. options 配置项。比如配置 multipledisabled是否显示 等等

举例如下:

config.js

export default [
  {
    
    
    type: 'el-input',
    label: '活动名称',
    formKey: 'name',
    value: '', // 默认值为空字符串
    options: {
    
    
      vIf: [
        // 表示:当 form.area === 'area1',才显示
        {
    
     relationKey: 'area', value: 'area1' }
      ]
    }
  },
  {
    
    
    type: 'el-select',
    label: '活动区域',
    formKey: 'area',
    value: 'area1',
    options: {
    
    
      multiple: true
    },
    optionData: [ // 这里模拟去后端拉回数据
      {
    
     label: '区域1', value: 'area1' },
      {
    
     label: '区域2', value: 'area2' }
    ]
  }
]

render function

FormItemDemo.vue

<script>
export default {
    
    
  name: "FormItemDemo",
  props: {
    
    
    itemConfig: Object // 接收配置,外部传入
  },
  computed: {
    
    
  componentShow () {
    
    
    const vIfArr = this.itemConfig?.options.vIf
    if (!vIfArr) return true
    const relationArr = this.config.filter(config => vIfArr.find(vIf => vIf.relationKey === config.formKey))
    for (const relationItem of relationArr) {
    
    
      const vIfItem = vIfArr.find(_ => _.relationKey === relationItem.formKey)
      // 这里就是判断 联动的表单值 是否不满足 可以显示 的条件,不满足则不显示
      if (relationItem.value !== vIfItem.value) return false
    }
    return true
  }
},
  render(createElement) {
    
    
  //render 执行时判断是否展示,不展示的话返回空即可
  if(this.componentShow) return
    return createElement('el-form-item', {
    
    
      props: {
    
    
        label: this.itemConfig.label // 表单项的label
      }
    }, [
        // 表单组件
        createElement(this.itemConfig.type, {
    
    
          props: {
    
    
            value: this.itemConfig.value // 这里是自己实现一个 v-model
          },
          on: {
    
    
            change: (nVal) => {
    
     // 这里是自己实现一个 v-model
              this.itemConfig.value = nVal
            }
          }
        }, this.itemConfig.optionData && this.itemConfig.optionData.map(option => {
    
    
          // 这里只是 本demo 处理 el-select 的 option 数据,实际大家根据具体业务来实现即可
          return createElement('el-option', {
    
     props: {
    
     label: option.label, value: option.value } })
        }))
    ])
  }
}
</script>

custom.vue

<template>
  <div>
    <el-form label-width="100px">
      <FormItemDemo v-for="item in config" :item-config="item" />
    </el-form>
  </div>
</template>

<script>
import FormItemDemo from "./components/FormItemDemo.vue";
import config from "./config";

export default {
    
    
  name: 'App',
  components: {
    
     FormItemDemo },
  data () {
    
    
    return {
    
    
      config
    }
  }
}
</script>

optimization function

This way our config is non-responsively optimized. In fact, for the entire config data, we just need to ensure that the value is responsive, and many other descriptive data are unnecessary. Then let's optimize other fields~

function optimize (array) {
    
    
  return array.reduce((acc, cur) => {
    
    
    for (const key of Object.keys(cur)) {
    
    
      if (key === 'value') continue
      // 将不是 value 的属性都进行非响应式优化
      Object.defineProperty(cur, [key], {
    
     enumerable: false })
    }
    acc.push(cur)
    return acc
  }, [])
}

Guess you like

Origin blog.csdn.net/baidu_39009276/article/details/126578248