
本文介绍在 Vue 2 中为基于 Select2 封装的多选 元素正确绑定 @change 事件并获取选中值的方法,重点解决原生 DOM 事件失效、v-model 同步异常等常见问题。
本文介绍在 vue 2 中为基于 select2 封装的多选 `
在 Vue.js(尤其是 Vue 2)中,直接对被第三方插件(如 Select2)封装的 <select></select> 元素使用原生 addEventListener('change') 往往无效——因为 Select2 会隐藏原生 <select></select> 并渲染自定义 DOM,其内部触发的变更不会冒泡到原生元素上。正确做法是结合 Vue 的响应式数据流与 Select2 的 API 回调机制,实现可靠监听。
✅ 推荐方案:Vue 响应式 + Select2 change 事件桥接
首先,确保 <select></select> 元素具备 Vue 可控性:添加 v-model 绑定,并为每个 <option></option> 显式设置 :value(推荐使用 id 而非 name,便于后端处理):
<select
id="invitees_list1"
class="form-select"
multiple
name="multi"
v-model="selectedInviteeIds"
@change="handleMultiSelectChange"
>
@foreach ($seatedTable->invitees as $invitee)
<option :value="{{ $invitee['id'] }}">
{{ $invitee['name'] }}
</option>
@endforeach
</select>⚠️ 注意:
v-model在多选<select></select>中必须绑定到数组(如selectedInviteeIds: []),否则将导致双向绑定失败。
接着,在 Vue 实例中定义处理方法及 Select2 初始化逻辑(关键!需在 mounted 中监听 Select2 的 change 事件,而非依赖 @change):
立即学习“前端免费学习笔记(深入)”;
const app = new Vue({
el: '#filtersContainer',
data: {
invitees: [],
selectedInviteeIds: [], // ✅ 必须初始化为空数组
// ...其余 data 字段保持不变
},
methods: {
handleMultiSelectChange() {
console.log('Vue v-model 已更新:', this.selectedInviteeIds);
// 此处可发起请求、校验、触发子组件事件等
this.$emit('multiSelectChanged', this.selectedInviteeIds);
},
// 辅助方法:同步 Select2 选中状态到 Vue 数据(可选,用于初始化回填)
syncSelect2ToVue() {
const $select = $('#invitees_list1');
const selectedValues = $select.val() || [];
this.selectedInviteeIds = Array.isArray(selectedValues)
? selectedValues.map(v => String(v))
: [String(selectedValues)];
}
},
mounted() {
// 初始化其他 Select2 组件...
$('#name_filter').select2();
$('#side_filter').select2();
// ...其他初始化
// ✅ 关键:为 invitees_list1 单独配置 Select2 并监听其 change 事件
$('#invitees_list1').select2().on('change', (e) => {
// 手动同步选中值到 Vue 响应式数据(兼容 Select2 异步操作)
this.selectedInviteeIds = e.val || [];
// 触发 Vue 方法(可复用已有逻辑)
this.handleMultiSelectChange();
});
// 若需初始值回填(如服务端已预选),调用 syncSelect2ToVue()
// this.syncSelect2ToVue();
}
});? 补充说明与最佳实践
为什么
@change单独不生效?
Vue 的@change监听的是原生<select></select>的 DOM 事件,而 Select2 替换了交互层,其变更由 jQuery 事件系统派发,因此必须通过.on('change')显式订阅。v-model与 Select2 共存是否冲突?
不冲突,但需注意:v-model控制的是 Vue 内部状态,Select2 控制的是 UI 展示;二者需通过事件桥接保持一致。上述代码中,Select2 的change回调主动更新this.selectedInviteeIds,从而驱动视图和后续逻辑。-
注意事项:
- 确保
selectedInviteeIds始终为字符串数组(Select2 返回值类型可能为字符串或数字,建议统一转为字符串以匹配:value类型); - 避免在
created或mounted中直接调用$select.val([...])修改值,应通过this.selectedInviteeIds = [...]触发 Vue 更新,再调用$select.trigger('change')同步 UI; - 如使用 Vue 3 + Composition API,推荐迁移到
vue-select或Element Plus等原生支持 Vue 的组件库,避免 jQuery 插件集成复杂度。
- 确保
通过以上方式,你就能稳定捕获多选框变更,并在 Vue 生态中无缝衔接业务逻辑。


















