如何优雅的使用v-bind集成动态属性的绑定

我们知道通过v-bind一个对象,便可以通过key与props做一个组件参数集成,一般都是用于静态属性绑定,如果我要在静态属性中绑定多个动态属性(如disabled属性由另一个按钮控制true,false),这种场景如何优雅的实现代码。虽然我实现了一个dome版本,但是实在不够优雅,有没有大神能指点一下,这类问题实在百度不到,跪谢了!

实现这个功能是为了将项目中的表单组件库抽象一个公共入口,直接配置JSON数据就可遍历生产页面和组件

详细代码在gitee仓库:gitee

线上效果地址:选择vbind下拉项

主入口index.vue

<template>
    <div>
        <component
            v-for="(item, index) in fields"
            :is="item.component"
            :key="index"
            v-bind="item"
            v-model="item.vmodel"
        ></component>
        <button @click="enableHandle">编辑/文本,变化</button>
        <button @click="disabledHandle">禁用,变化</button>
    </div>
</template>

<script>
import variableFormat from './field.js'

export default {
    data() {
        return {
            fields: [],
            enable: true,
            disabled: true,
        }
    },
    computed: {
        enableCom: {
            get() {
                return this.enable
            },
            set(v) {
                this.fields = this.fields.map((e) => {
                    e.enable = v
                    return e
                })
                this.enable = v
            },
        },
        disabledCom: {
            get() {
                return this.disabled
            },
            set(v) {
                this.fields = this.fields.map((e) => {
                    e.disabled = v
                    return e
                })
                this.disabled = v
            },
        },
    },
    methods: {
        enableHandle() {
            this.enableCom = !this.enableCom
        },
        disabledHandle() {
            this.disabledCom = !this.disabledCom
        },
    },
    created() {
        this.fields = variableFormat(this)
    },
}
</script>

<style>
</style>

input组件

<template>
    <div>
        <h1>input:</h1>
        <el-input v-if="enable" :disabled="disabled" v-model="model" />
        <span v-else>{{ value || '---' }}</span>
    </div>
</template>

<script>
export default {
    props: {
        value: { type: String },
        enable: { type: Boolean },
        disabled: { type: Boolean },
    },
    data(){
        return {
            model: ''
        }
    },
    watch: {
        model(newVal) {
            this.$emit('input', newVal)
        },
    },
}
</script>

<style>
</style>

select组件

<template>
    <div>
        <h1>select:</h1>
        <el-select
            v-if="enable"
            class="path-select"
            v-model="model"
            filterable
            placeholder="请选择"
            :disabled="disabled"
        >
            <el-option
                v-for="(item, index) in options"
                :key="index"
                :label="item.label"
                :value="item.value"
            >
            </el-option>
        </el-select>
        <span v-else>{{ value || '---' }}</span>
    </div>
</template>

<script>
export default {
    props: {
        value: { type: [Number,String] },
        enable: { type: Boolean },
        disabled: { type: Boolean },
        options: { type: Array },
    },
    data() {
        return {
            model: '',
        }
    },
    watch: {
        model(newVal) {
            this.$emit('input', newVal)
        },
    },
}
</script>

<style>
</style>

字段配置

import ZbInput from './ZbInput'
import ZbSelect from './ZbSelect'

const field = [{
        vmodel: '',
        enable: true, // 可切换的动态值
        disabled: false, // 可切换的动态值
        component: ZbInput,
    },
    {
        vmodel: '',
        enable: true, // 可切换的动态值
        disabled: false, // 可切换的动态值
        options: [{ label: '张三', value: 1 }, { label: '李四', value: 2 }],
        component: ZbSelect,
    }
]

const variableFormat = vm => {
    return field.map(e => {
        e.enable = vm.enableCom
        e.disabled = vm.disabledCom
        return e
    })
}
export default variableFormat