el-select-v2 组件使用问题
直接给 props
赋值会导致滚动后选中选项之后会回滚到顶部问题分析
在 Vue 和 Element Plus 的虚拟化选择器中,直接将对象字面量赋值给 :props
属性(如 :props="{ label: "name", value: "id" }"
)会导致每次选中选项后回滚到顶部,而使用预定义的对象(如 props
)则不会出现这个问题。以下是详细分析:
1. 对象字面量的重新创建
当使用 :props="{ label: "name", value: "id" }"
时,每次组件重新渲染时,Vue 会重新创建一个新的对象。这会导致以下问题:
- 对象引用变化 :虚拟化选择器会检测到
props
的变化(因为对象引用发生了变化),认为props
是一个新的值。 - 重新渲染选项列表:虚拟化选择器会重新渲染选项列表,导致滚动位置被重置到顶部。
2. 预定义对象的稳定性
当使用预定义的对象(如 config
)时:
ts
const props = {
label: "name",
value: "id",
};
- 对象引用不变 :
props
的引用在整个组件生命周期内保持稳定,Vue 不会认为props
发生了变化。 - 避免不必要的重新渲染:虚拟化选择器不会重新渲染选项列表,从而保留滚动位置。
3. 虚拟化组件的优化机制
虚拟化组件(如 el-select-v2
)通常会根据 props
的变化来决定是否重新渲染选项列表:
- 如果
props
的引用发生变化,组件会重新计算和渲染选项列表。 - 如果
props
的引用保持不变,组件会复用现有的选项列表,避免滚动位置重置。
解决方案总结
- 避免使用对象字面量 :直接使用对象字面量赋值给
:props
会导致每次渲染时创建新的对象,触发虚拟化组件的重新渲染。 - 使用预定义对象 :通过定义一个稳定的对象(如
config
),可以避免对象引用变化,从而避免滚动位置重置。
示例对比
有问题的代码:
vue
<el-select-v2 :props="{ label: "name", value: "id" }" />
- 每次渲染都会创建新的对象,导致滚动位置重置。
正确的代码:
vue
<el-select-v2 :props="props" />
- 使用稳定的对象引用,避免滚动位置重置。
根本原因
这种问题的根本原因是 Vue 的响应式机制和虚拟化组件的渲染逻辑共同作用导致的。通过优化 props
的赋值方式,可以有效解决问题。