Bootstrap

动态表单探索(二)—— 联动优化

前言

前文联动修改通过深层遍历匹配方式去解决,若表达内容庞大复杂就会显得很繁琐,而且性能不高。为解决这一问题,考虑通过订阅发布的方式去触发相关联动的改变。

改进内容

修改数据结构

1、添加option用于携带自身相关属性;
2、triggers为联动数组(便于绑定多个内容),用于联动相关元素,发布事件;
3、action为订阅内容,监听相应事件,修改自身状态

<template>
  <div class="call_status">
      <HdfComponent v-for="(item,index) in treeData" :key="index" :itemData="item"></HdfComponent>
  </div>
</template>

<script>
import HdfComponent from './components/HdfComponent.vue'
export default {
    data(){
        return {
            treeData:[{
                name: 'name',
                type: 'HdfComp',
                label: '医生姓名',
                options: {
                    value: '',
                    status: '1',
                    content: '',
                    child: [{
                        name: 'name',
                        type: 'HdfInput',
                        label: '医生姓名',
                        options: {
                            value: '',
                            status: '1',
                            content: '',
                            child: '',
                            triggers: [],
                            action: ''
                        }
                    }],
                    triggers: [],
                    action: ''
                }
            },{
                name: 'sex',
                type: 'HdfRadio',
                label: '性别',
                options: {
                    value: '',
                    status: '1',
                    content:  [{
                        label: '男',
                        value: 1
                    },{
                        label: '女',
                        value: 0
                    }],
                    child: '',
                    triggers: ['isPregnant','edc1'],
                    action: ''
                }
            },{
                name: 'area',
                type: 'HdfInput',
                label: '地区',
                options: {
                    value: '',
                    status: '1',
                    content: '',
                    child: '',
                    triggers: [],
                    action: ''
                }
            },{
                name: 'height',
                type: 'HdfInput',
                label: '身高',
                unit: '厘米',
                options: {
                    value: '',
                    status: '1',
                    content: '',
                    child: '',
                    triggers: [],
                    action: ''
                }
            },{
                name: 'isPregnant',
                type: 'HdfRadio',
                label: '是否孕期',
                options: {
                    value: '',
                    status: '0',
                    content:  [{
                        label: '是',
                        value: 1
                    },{
                        label: '否',
                        value: 0
                    }],
                    child: '',
                    triggers: ['edc'],
                    action: `
                        this.$EventBus.$on('isPregnant', (data) => {
                            if(data === 0){
                                this.itemData.options.status = '1'
                            }else{
                                this.itemData.options.status = '0'
                            }
                        })
                    `
                }
            },{
                name: 'edc',
                type: 'HdfDatePicker',
                label: '预产期',
                options: {
                    value: '',
                    status: '0',
                    content: '',
                    child: '',
                    triggers: [],
                    action: `
                        this.$EventBus.$on('edc', (data) => {
                            if(data === 1){
                                this.itemData.options.status = '1'
                            }else{
                                this.itemData.options.status = '0'
                            }
                        })
                        this.$EventBus.$on('edc1', (data) => {
                            if(data === 1){
                                this.itemData.options.status = '0'
                            }
                        })
                    `
                }
            }]
        }
    },
    components: {
        HdfComponent
    }
}
</script>

联动处理

1、订阅内容通过字符串的形式绑定,需要eval解析为代码;
2、遍历triggers依次发布相关事件进行触发。

<template>
    <div>
        <component class="itemContent" v-bind:is="itemData.type" @event1="change($event)" v-if="itemData.options.status==='1'" v-model="itemData"></component>
    </div>
</template>

<script>
    import moduleComponents from '../util/getBasicArr.js';
    export default {
        name: 'HdfComponent',
        props:{
            itemData:{
                default: () => ({}),
                type: Object
            }
        },
        mounted(){
            if(this.itemData.options.action){
                eval(this.itemData.options.action)
            }
        },
        methods: {
            change(data) {
                const triggers = this.itemData.options.triggers
                if(triggers.length > 0){
                    triggers.forEach(item => {
                        this.$EventBus.$emit(item, data)
                    })
                }
            }
        },
        components: moduleComponents
    }
</script>

<style lang="scss" scoped>
.itemContent{
    padding: 10px;
}
</style>
;