Transfer穿梭框选中项无法双向绑定是怎么回事?
我用Element Plus的Transfer组件做权限分配,明明设置了v-model绑定selectedKeys,但右边已选列表变了,selectedKeys却没更新,控制台打印还是空数组。是我哪里写错了吗?
这是我的代码:
<el-transfer
v-model="selectedKeys"
:data="roleOptions"
:props="{ key: 'id', label: 'name' }"
/>
roleOptions是正常的数据源,selectedKeys初始化为[],但操作后它始终不变。
let selectedKeys = []?改成const selectedKeys = ref([])就好了。如果用的是 Options API,那得写成
data() { return { selectedKeys: [] } },别用data: { selectedKeys: [] }这种错写法。再检查下有没有在模板里漏写
v-model的修饰符,比如.lazy,别加那个,Transfer 必须用默认的同步更新。v-model没有正确配合change事件,或者数据源结构不匹配,就会出现“界面变了,但绑定值没更新”的情况。你现在的代码只写了
v-model="selectedKeys",但没监听change事件,这是最常见的坑。Element Plus 的 Transfer 并不会自动把选中项同步回v-model绑定的变量——它需要你主动通过change事件接收新值并赋值回去。不过等等,先别急着加
@change,我们先确认几个关键点,一步步排查:第一:检查
roleOptions里的id是否是字符串类型?Element Plus 的 Transfer 内部比较 key 的时候,用的是严格相等(
===),如果你的id是数字类型(比如1, 2, 3),而v-model绑定的是字符串数组(比如["1", "2"]),它会认为“没选中”,导致双向绑定失效。✅ 建议统一用字符串类型的
id,哪怕后端返回的是数字,前端也转换一下:或者在拿到数据后做一次转换:
第二:加上
@change事件,手动同步值。Transfer 的
change事件签名是(value: string[] | number[], direction: 'left' | 'right', movedKeys: string[] | number[]),其中第一个参数value就是当前所有已选中的 key,你得把它赋给selectedKeys。✅ 正确写法是这样的:
第三:别忘了检查
v-model和:data的配合逻辑。如果
roleOptions里某个id是undefined或null,Transfer 会忽略它,但不会报错,结果就是你选了,但selectedKeys里没它。你可以在控制台打印下
roleOptions的前几项确认:最后补充一个容易被忽略的点:
如果你用了
filterable(搜索功能),Transfer 会把搜索框的值也参与 key 匹配,导致选中异常。如果不需要搜索,建议先关掉filterable排除干扰:我之前踩过这个坑,就是以为
v-model是自动双向的,结果发现 Transfer 根本没触发响应式更新——它依赖你手动同步。Element Plus 的很多组件都是这种“给事件你,自己处理”的风格,不是像 Vue 自带的input那样自动同步。你按上面三步改完,应该就能用了。如果还是不行,把
roleOptions的结构贴出来,我帮你看看是不是id类型或者嵌套问题。