在Vue中如何使用v-bind、v-on为自定义命名model完成绑定?
解决方案
针对Vue2环境下BootstrapVue组件的v-model动态透传需求,提供两种可落地的方案,均不需要修改现有封装的校验、样式逻辑:
方案1:轻量手动适配(无需提前维护配置)
仅需修改InputWrapper组件,新增两个可选prop用于自定义model的绑定属性和触发事件,默认值兼容原生表单组件的value+input组合。
修改后的InputWrapper.vue代码
<template> <div> <slot v-bind="wrappedBindings"></slot> </div> </template> <script> export default { props: { value: { required: true }, // 新增:自定义model绑定的属性名,默认value modelProp: { type: String, default: 'value' }, // 新增:自定义model触发的事件名,默认input modelEvent: { type: String, default: 'input' } }, methods: { onInput($event){ this.$emit('input', $event); } }, computed: { wrappedBindings(){ return { attrs: { [this.modelProp]: this.value }, on: { [this.modelEvent]: $event => this.onInput($event) } } } } } </script>
使用示例
<div> <!-- b-form-select默认匹配,无需额外配置 --> <input-wrapper v-model="selectModel" v-slot="{attrs, on}"> <b-form-select v-bind="attrs" v-on="on"></b-form-select> </input-wrapper> <!-- b-form-input事件名为update,指定modelEvent即可 --> <input-wrapper v-model="inputModel" model-event="update" v-slot="{attrs, on}"> <b-form-input v-bind="attrs" v-on="on"></b-form-input> </input-wrapper> <!-- b-form-checkbox绑定属性为checked,指定modelProp即可 --> <input-wrapper v-model="checkModel" model-prop="checked" v-slot="{attrs, on}"> <b-form-checkbox v-bind="attrs" v-on="on"></b-form-checkbox> </input-wrapper> </div>
方案2:零配置适配(内置BootstrapVue组件映射表)
如果团队使用的BootstrapVue表单组件相对固定,可以提前把所有组件的model配置内置到InputWrapper中,使用者不需要查阅文档,仅需指定组件类型即可自动适配。
新增映射表的InputWrapper核心代码
<script> // 预先维护所有用到的BootstrapVue表单组件的model配置 const BS_FORM_MODEL_MAP = { 'b-form-input': { prop: 'value', event: 'update' }, 'b-form-select': { prop: 'value', event: 'input' }, 'b-form-checkbox': { prop: 'checked', event: 'input' }, 'b-form-radio': { prop: 'checked', event: 'input' }, 'b-form-textarea': { prop: 'value', event: 'update' }, 'b-form-switch': { prop: 'checked', event: 'input' } // 后续新增组件仅需在此补充配置即可 } export default { props: { value: { required: true }, modelProp: { type: String, default: 'value' }, modelEvent: { type: String, default: 'input' }, // 新增:指定BootstrapVue组件类型,自动匹配model配置 componentType: { type: String, default: '' } }, methods: { onInput($event){ this.$emit('input', $event); } }, computed: { // 优先级:手动传入的modelProp > 映射表匹配的prop > 默认value finalProp() { if (this.modelProp !== 'value') return this.modelProp return BS_FORM_MODEL_MAP[this.componentType]?.prop || 'value' }, // 优先级:手动传入的modelEvent > 映射表匹配的event > 默认input finalEvent() { if (this.modelEvent !== 'input') return this.modelEvent return BS_FORM_MODEL_MAP[this.componentType]?.event || 'input' }, wrappedBindings(){ return { attrs: { [this.finalProp]: this.value }, on: { [this.finalEvent]: $event => this.onInput($event) } } } } } </script>
使用示例
<div> <input-wrapper v-model="selectModel" component-type="b-form-select" v-slot="{attrs, on}"> <b-form-select v-bind="attrs" v-on="on"></b-form-select> </input-wrapper> <input-wrapper v-model="inputModel" component-type="b-form-input" v-slot="{attrs, on}"> <b-form-input v-bind="attrs" v-on="on"></b-form-input> </input-wrapper> <input-wrapper v-model="checkModel" component-type="b-form-checkbox" v-slot="{attrs, on}"> <b-form-checkbox v-bind="attrs" v-on="on"></b-form-checkbox> </input-wrapper> </div>
两种方案均不需要为每个组件单独封装,仅需维护一次公共配置即可覆盖所有表单组件的v-model透传需求,维护成本极低。
内容的提问来源于stack exchange,提问作者Stefmachine
相关产品推荐
相关产品推荐

