vue穿梭框组件通过emit('update:modelvalue', {left, right})回传左右侧最新状态,涵盖点击移动、全选/取消、搜索过滤、拖拽排序等操作;子组件用syncstate统一处理去重、互斥并emit,父组件响应式更新需深拷贝数据。

Vue 中穿梭框(Transfer)组件通过 emit 回传左右两侧数据变动,核心是子组件在数据变更时主动触发自定义事件,把当前状态(如左侧剩余项、右侧已选项)作为参数通知父组件。这不是简单地 emit 一次,而是围绕“选中切换”“批量移动”“搜索过滤后重算”等操作,在关键节点 emit 合适的数据结构。
以下分三部分说明实现要点:
穿梭框中哪些操作需要 emit 数据变动
- 用户点击「→」按钮,把左侧选中项移到右侧
- 用户点击「←」按钮,把右侧选中项移回左侧
- 全选/取消全选左侧或右侧列表
- 搜索框输入导致可视列表变化(若需同步已选状态)
- 拖拽排序(如果支持,右侧顺序变化也应 emit)
每次操作后,子组件应重新计算并 emit 当前完整的业务态,例如:
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
emit('update:modelValue', {
left: remainingLeftItems, // 左侧剩余数据(未被选中的)
right: selectedRightItems // 右侧最终数据(含新增/移除/重排)
})
这样父组件拿到的是确定的、可直接替换的最新状态,避免靠 diff 推断逻辑。
子组件内部如何组织 emit 逻辑
- 使用
defineEmits(['update:modelValue', 'change'])明确声明事件 - 所有修改动作(如
moveToRight)最后都调用统一的syncState()方法 -
syncState()负责:- 过滤掉 disabled 项
- 剔除重复 key(按
props.keyField去重) - 保证 left/right 数据互斥(一个 item 不会同时出现在两边)
- 将结果包装为对象 emit 出去
示例片段:
const emit = defineEmits(['update:modelValue'])
function moveToRight() {
const selected = leftData.filter(item => item.checked)
rightData.push(...selected.map(item => ({ ...item })))
leftData = leftData.filter(item => !item.checked)
syncState()
}
function syncState() {
emit('update:modelValue', {
left: leftData,
right: rightData
})
}
父组件如何响应并保持响应式
- 在模板中绑定
v-model:left-data和v-model:right-data(推荐)
或显式写成<customtransfer></customtransfer> -
onTransferChange接收对象,直接赋值给响应式数据:const leftList = ref([]) const rightList = ref([])
function onTransferChange({ left, right }) { leftList.value = left rightList.value = right }
- 若使用 `v-model`,需在子组件内正确支持 `modelValue` + `update:modelValue` 的约定,Vue 3 会自动识别为双向绑定。 不复杂但容易忽略的是:**emit 的数据必须是深拷贝后的纯净数组,不能包含响应式代理或副作用引用**,否则父组件更新可能引发意外 rerender 或警告。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










