vue使用jsx+策略模式解决大量v-else-if

1,390 阅读2分钟

重构设备操作弹出框

设备总共有40多个一级类型 80多个二级类型 每个一级类型的操作各不相同,二级类型的操作也有细微的不同 后续可能还会增加设备 公司之前的代码多达2w行 现在已成shi山 代码也基本告别了复用,template 充斥这大量的v-else-if 也难以维护 现在有两处要使用设备操作弹出框 复用已经根本不切实际 唯有重构

说说之前代码弊病

二级类型直接写成一个数组通过indexof去匹配设备

举个例子

现有两个设备

    • 普通灯

      操作 开\关\配对

    • 冷暖灯

      操作 开\关\配对\亮度\色温

  1. 空调

    • 普通空调

      开\关\温度\配对\模式\风速

。。。。

到底该如何重构,因为之前学习过react瞬间相当了jsx 再结合vue官网cn.vuejs.org/v2/guide/re… 于是乎果断使用了jsx,使用方法、依赖请参考github.com/vuejs/jsx

说干就干

  1. 封装dialog

//index.jsx
props: {
      dialogVisible: Boolean 
      deviceInfo:Object //设备info 应当存在 一级类型 二级类型 设备id
    },
render(h){
    const component = deviceOperationGenerator(h,devFirstType,devSecondType,jdlDeviceId)
    // js的弊病出现了 没有类型约束 还得学ts 封装一个打印信息函数 思路:判断deviceInfo 是否存在一级类型 二级类型 设备id 如上不存在应该console.error() 
 	return (
    	<el-dialog>
        	{conmponent}
        </el-dialog>
    )   
}
  1. 实现核心

//core.js deviceOperationGenerator
const deviceOperationGenerator = function(h,devFirstType,devSecondType,jdlDeviceId){
// 策略模式 判断一级类型 根据一级类型进入二级类型 当增加一级类型只需按照这个的代码规范即可
    const components = {
      1:() => switchGenerator(h,devSecondType,jdlDeviceId),
      2:() => scoketGenerator(h,devSecondType,jdlDeviceId),
      3:() => doorLockGenertor(h,devSecondType,jdlDeviceId),
      4:() => airConditionerGenertor(h,devSecondType,jdlDeviceId),
      6:() => curtainGenertor(h,devSecondType,jdlDeviceId),
      8:() => securityGatewayGenerator(h,devSecondType,jdlDeviceId),
      10:() => infraredAlarmGenertor(h,devSecondType,jdlDeviceId),
      17:() => controlBoxGenertor(h,devSecondType,jdlDeviceId),
      23:() => lampGenerator(h,devSecondType,jdlDeviceId),
      31:() => adjustingLampGenertor(h,devSecondType,jdlDeviceId),
      notfound:<div style="color:green;font-size:16px;">功能正在加紧开发敬请稍后...</div>
    }
    // 容错处理
    if(components[devFirstType]){
      return components[devFirstType]
    }
    return components['notfound']
  }
export default deviceOperationGenerator
  1. 二级类型函数实现 跟一级类型类似

  2. 使用混入+slot减少重复代码

    tips: 这里也出现了js的弊病 没有类型约束 只有通过约定了 我在设备弹窗那个组件写了README.md

//基础组件 窗帘
<template>
    <div>
        <div class="flex">
            <el-button type="primary" @click="clickBtn('开')">开</el-button>
            <el-button type="primary" @click="clickBtn('关')">关</el-button>
            <el-button type="primary" @click="clickBtn('暂停')">暂停</el-button>
            <slot name="button"/>
        </div>
        <div>
            <slot name="slider"/>
        </div>
    </div>
</template>

<script>
import { simpleOperationMixin } from '../mixin'
export default {
    props:{
        deviceId:Number
    },
    mixins:[simpleOperationMixin]
}
</script>

<style scoped>
.flex{
    display: flex;
}
</style>

//基于基础组件实现增加其他控制
<template>
    <Curtain :deviceId="deviceId">
        <div slot="button"  style="margin-left:10px">
            <el-button type="primary" @click="clickBtn('正装')">正转</el-button>
            <el-button type="primary" @click="clickBtn('反转')">反转</el-button>
            <el-button type="primary" @click="pair">配对</el-button>
        </div>
        <div slot="slider">
            <el-form label-position="right" >
                <el-form-item label-width="130px" label="转速调整:">
                <el-slider @change="changeSlider" v-model="form.devPercentage" :max="99" :min="1" :step="10" style="width: 80%">
                </el-slider>
            </el-form-item>
            </el-form>
        </div>
    </Curtain>
</template>

<script>
import Curtain from './curtain.vue'
import { simpleOperationMixin,sliderMixin } from '../mixin'
export default {
    props:{
        deviceId:Number
    },
    components:{
        Curtain
    },
    mixins:[simpleOperationMixin,sliderMixin],
    data(){
        return {
             form:{
                devId:this.deviceId,
                devPercentage:50
            }
        }
    }
}
</script>