Select V2 虚拟列表选择器beta

TIP

这个组件目前在测试当中,如果在使用中发现任何漏洞和问题,请在 GitHub Virtualized Select 虚拟化选择器 - 图1 中提交 issue 以便我们进行处理。

背景

在某些使用情况下,单个选择器可能最终加载数万行数据。 将这么多的数据渲染至 DOM 中可能会给浏览器带来负担,从而造成性能问题。 为了更好的用户和开发者体验,我们决定添加此组件。

基础用法

适用广泛的基础选择器

Virtualized Select 虚拟化选择器 - 图2

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. :options="options"
  5. placeholder="Please select"
  6. size="large"
  7. />
  8. <el-select-v2
  9. v-model="value"
  10. :options="options"
  11. placeholder="Please select"
  12. />
  13. <el-select-v2
  14. v-model="value"
  15. :options="options"
  16. placeholder="Please select"
  17. size="small"
  18. />
  19. </template>
  20. <script lang="ts" setup>
  21. import { ref } from 'vue'
  22. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  23. const value = ref('')
  24. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  25. value: `Option ${idx + 1}`,
  26. label: `${initials[idx % 10]}${idx}`,
  27. }))
  28. </script>
  29. <style scoped>
  30. .example-showcase .el-select-v2 {
  31. margin-right: 20px;
  32. }
  33. </style>

多选

最基础的多选选择器

Virtualized Select 虚拟化选择器 - 图3

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. :options="options"
  5. placeholder="Please select"
  6. style="width: 240px"
  7. multiple
  8. />
  9. </template>
  10. <script lang="ts" setup>
  11. import { ref } from 'vue'
  12. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  13. const value = ref([])
  14. const options = ref(
  15. Array.from({ length: 1000 }).map((_, idx) => ({
  16. value: `Option ${idx + 1}`,
  17. label: `${initials[idx % 10]}${idx}`,
  18. }))
  19. )
  20. </script>

隐藏多余标签的多选

默认情况下选中值会以 Tag 的形式展现,你也可以设置collapse-tags属性将它们合并为一段文字。 您可以使用 collapse-tags-tooltip 属性来启用鼠标悬停折叠文字以显示具体所选值的行为。

Virtualized Select 虚拟化选择器 - 图4

  1. <template>
  2. <div style="display: inline-block">
  3. <p style="margin: 10px">use collapse-tags</p>
  4. <el-select-v2
  5. v-model="value"
  6. :options="options"
  7. placeholder="Please select"
  8. style="width: 240px"
  9. multiple
  10. collapse-tags
  11. />
  12. </div>
  13. <div style="display: inline-block; margin-left: 20px">
  14. <p style="margin: 10px">use collapse-tags-tooltip</p>
  15. <el-select-v2
  16. v-model="value2"
  17. :options="options"
  18. placeholder="Please select"
  19. style="width: 240px"
  20. multiple
  21. collapse-tags
  22. collapse-tags-tooltip
  23. />
  24. </div>
  25. </template>
  26. <script lang="ts" setup>
  27. import { ref } from 'vue'
  28. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  29. const value = ref([])
  30. const value2 = ref([])
  31. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  32. value: `Option ${idx + 1}`,
  33. label: `${initials[idx % 10]}${idx}`,
  34. }))
  35. </script>

可过滤的多选

当选项太多时,你可以使用 filterable 选项来启用过滤功能来找到所需的选项。

Virtualized Select 虚拟化选择器 - 图5

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. filterable
  5. :options="options"
  6. placeholder="Please select"
  7. style="width: 240px"
  8. multiple
  9. />
  10. </template>
  11. <script lang="ts" setup>
  12. import { ref } from 'vue'
  13. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  14. const value = ref([])
  15. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  16. value: `Option${idx + 1}`,
  17. label: `${initials[idx % 10]}${idx}`,
  18. }))
  19. </script>

禁用选择器本身或选项

您可以选择禁用 Select 或者 Select 中的某个选项

Virtualized Select 虚拟化选择器 - 图6

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. filterable
  5. :options="options"
  6. placeholder="Please select"
  7. style="width: 240px; margin-right: 16px; vertical-align: middle"
  8. multiple
  9. />
  10. <el-select-v2
  11. v-model="value"
  12. disabled
  13. filterable
  14. :options="options"
  15. placeholder="Please select"
  16. style="width: 240px; vertical-align: middle"
  17. multiple
  18. />
  19. </template>
  20. <script lang="ts" setup>
  21. import { ref } from 'vue'
  22. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  23. const value = ref([])
  24. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  25. value: `Option${idx + 1}`,
  26. label: `${initials[idx % 10]}${idx}`,
  27. disabled: idx % 10 === 0,
  28. }))
  29. </script>

给选项进行分组

只要数据格式满足特定要求,我们就可以按照自己的意愿为选项进行分组。

Virtualized Select 虚拟化选择器 - 图7

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. filterable
  5. :options="options"
  6. placeholder="Please select"
  7. style="width: 240px"
  8. multiple
  9. />
  10. </template>
  11. <script lang="ts" setup>
  12. import { ref } from 'vue'
  13. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  14. const value = ref([])
  15. const options = Array.from({ length: 10 }).map((_, idx) => {
  16. const label = idx + 1
  17. return {
  18. value: `Group ${label}`,
  19. label: `Group ${label}`,
  20. options: Array.from({ length: 10 }).map((_, idx) => ({
  21. value: `Option ${idx + 1 + 10 * label}`,
  22. label: `${initials[idx % 10]}${idx + 1 + 10 * label}`,
  23. })),
  24. }
  25. })
  26. </script>

自定义选项的渲染模板

我们也可以通过自定义模板来渲染自己想要的选项内容。

Virtualized Select 虚拟化选择器 - 图8

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. filterable
  5. :options="options"
  6. placeholder="Please select"
  7. style="width: 240px"
  8. multiple
  9. >
  10. <template #default="{ item }">
  11. <span style="margin-right: 8px">{{ item.label }}</span>
  12. <span style="color: var(--el-text-color-secondary); font-size: 13px">
  13. {{ item.value }}
  14. </span>
  15. </template>
  16. </el-select-v2>
  17. </template>
  18. <script lang="ts" setup>
  19. import { ref } from 'vue'
  20. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  21. const value = ref([])
  22. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  23. value: `Option ${idx + 1}`,
  24. label: `${initials[idx % 10]}${idx}`,
  25. }))
  26. </script>

一键清除

我们可以同时清除所有选定的选项。此设定也可适用于单选。

Virtualized Select 虚拟化选择器 - 图9

  1. <template>
  2. <el-select-v2
  3. v-model="value1"
  4. :options="options"
  5. placeholder="Please select"
  6. style="width: 240px; margin-right: 16px; vertical-align: middle"
  7. multiple
  8. clearable
  9. />
  10. <el-select-v2
  11. v-model="value2"
  12. :options="options"
  13. placeholder="Please select"
  14. style="width: 240px; vertical-align: middle"
  15. clearable
  16. />
  17. </template>
  18. <script lang="ts" setup>
  19. import { ref } from 'vue'
  20. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  21. const value1 = ref([])
  22. const value2 = ref('')
  23. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  24. value: `Option ${idx + 1}`,
  25. label: `${initials[idx % 10]}${idx}`,
  26. }))
  27. </script>

创建临时选项

可以创建并选中未包含在初始选项中的条目。

通过使用 allow-create 属性,用户可以通过输入框创建新项目。 为了使 allow-create 正常工作, filterable 的值必须为 true

TIP

最好在使用 allow-create 属性的同时设置 :reserve-keyword="false"

Virtualized Select 虚拟化选择器 - 图10

  1. <template>
  2. <div style="flex: auto">
  3. <div>
  4. <el-select-v2
  5. v-model="value1"
  6. :options="options"
  7. placeholder="Please select"
  8. style="width: 240px; margin-right: 16px; vertical-align: middle"
  9. allow-create
  10. filterable
  11. multiple
  12. clearable
  13. />
  14. <el-select-v2
  15. v-model="value2"
  16. :options="options"
  17. placeholder="Please select"
  18. style="width: 240px; vertical-align: middle"
  19. allow-create
  20. filterable
  21. clearable
  22. />
  23. </div>
  24. <div>
  25. <p style="margin-top: 20px; margin-bottom: 8px">
  26. set reserve-keyword false
  27. </p>
  28. <el-select-v2
  29. v-model="value3"
  30. :options="options"
  31. placeholder="Please select"
  32. style="width: 240px; margin-right: 16px; vertical-align: middle"
  33. allow-create
  34. filterable
  35. multiple
  36. clearable
  37. :reserve-keyword="false"
  38. />
  39. </div>
  40. </div>
  41. </template>
  42. <script lang="ts" setup>
  43. import { ref } from 'vue'
  44. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  45. const value1 = ref([])
  46. const value2 = ref('')
  47. const value3 = ref([])
  48. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  49. value: `Option ${idx + 1}`,
  50. label: `${initials[idx % 10]}${idx}`,
  51. }))
  52. </script>

远程搜索

输入关键字以从远程服务器中查找数据。

为了启用远程搜索,需要将 filterableremote 设置为 true,同时传入一个 remote-methodremote-method 为一个 Function,它会在输入值发生变化时调用,参数为当前输入值。

Virtualized Select 虚拟化选择器 - 图11

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. style="width: 240px"
  5. multiple
  6. filterable
  7. remote
  8. :remote-method="remoteMethod"
  9. clearable
  10. :options="options"
  11. :loading="loading"
  12. placeholder="Please enter a keyword"
  13. />
  14. </template>
  15. <script lang="ts" setup>
  16. import { ref } from 'vue'
  17. const states = [
  18. 'Alabama',
  19. 'Alaska',
  20. 'Arizona',
  21. 'Arkansas',
  22. 'California',
  23. 'Colorado',
  24. 'Connecticut',
  25. 'Delaware',
  26. 'Florida',
  27. 'Georgia',
  28. 'Hawaii',
  29. 'Idaho',
  30. 'Illinois',
  31. 'Indiana',
  32. 'Iowa',
  33. 'Kansas',
  34. 'Kentucky',
  35. 'Louisiana',
  36. 'Maine',
  37. 'Maryland',
  38. 'Massachusetts',
  39. 'Michigan',
  40. 'Minnesota',
  41. 'Mississippi',
  42. 'Missouri',
  43. 'Montana',
  44. 'Nebraska',
  45. 'Nevada',
  46. 'New Hampshire',
  47. 'New Jersey',
  48. 'New Mexico',
  49. 'New York',
  50. 'North Carolina',
  51. 'North Dakota',
  52. 'Ohio',
  53. 'Oklahoma',
  54. 'Oregon',
  55. 'Pennsylvania',
  56. 'Rhode Island',
  57. 'South Carolina',
  58. 'South Dakota',
  59. 'Tennessee',
  60. 'Texas',
  61. 'Utah',
  62. 'Vermont',
  63. 'Virginia',
  64. 'Washington',
  65. 'West Virginia',
  66. 'Wisconsin',
  67. 'Wyoming',
  68. ]
  69. const list = states.map((item): ListItem => {
  70. return { value: `value:${item}`, label: `label:${item}` }
  71. })
  72. interface ListItem {
  73. value: string
  74. label: string
  75. }
  76. const value = ref([])
  77. const options = ref<ListItem[]>([])
  78. const loading = ref(false)
  79. const remoteMethod = (query: string) => {
  80. if (query !== '') {
  81. loading.value = true
  82. setTimeout(() => {
  83. loading.value = false
  84. options.value = list.filter((item) => {
  85. return item.label.toLowerCase().includes(query.toLowerCase())
  86. })
  87. }, 200)
  88. } else {
  89. options.value = []
  90. }
  91. }
  92. </script>

使用 value-key

options.value 是一个对象时,您需要指定一个 key

Virtualized Select 虚拟化选择器 - 图12

  1. <template>
  2. <el-select-v2
  3. v-model="value"
  4. :options="options"
  5. placeholder="Please select"
  6. value-key="value.name"
  7. />
  8. </template>
  9. <script lang="ts" setup>
  10. import { ref } from 'vue'
  11. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  12. const value = ref('')
  13. const options = Array.from({ length: 1000 }).map((_, idx) => ({
  14. value: {
  15. name: `Option ${idx + 1}`,
  16. test: `test ${idx % 3}`,
  17. },
  18. label: `${initials[idx % 10]}${idx}`,
  19. }))
  20. </script>
  21. <style scoped>
  22. .example-showcase .el-select-v2 {
  23. margin-right: 20px;
  24. }
  25. </style>

SelectV2 属性

属性说明类型可选值默认值
model-value / v-model绑定值string / number / boolean / object
multiple是否多选booleanfalse
disabled是否禁用booleanfalse
value-key作为 value 唯一标识的键名,绑定值为对象类型时必填stringvalue
size输入框尺寸stringlarge/default/smalldefault
clearable是否可以清空选项booleanfalse
clear-icon自定义清除图标string | ComponentCircleClose
collapse-tags多选时是否将选中值按文字的形式展示booleanfalse
collapse-tags-tooltip当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。 只有当 collapse-tags 设置为 true 时才会生效。booleantrue / falsefalse
multiple-limit多选时可被选择的最大数目。 当被设置为0时,可被选择的数目不设限。number0
name选择器的原生name属性string
effect文字提示(Tooltip)的主题,内置darklight两种。stringstringlight
autocomplete自动完成选择输入stringoff
placeholderselect input的原生autocomplete属性stringPlease select
filterable是否可筛选booleanfalse
allow-create是否允许创建新条目, 当使用该属性时,filterable必须设置为truebooleanfalse
reserve-keyword筛选时,是否在选择选项后保留关键字booleantrue
no-data-text当在没有数据时显示的文字,你同时可以使用#empty插槽进行设置。stringNo Data
popper-class选择器下拉菜单的自定义类名string
popper-append-to-body(deprecated)是否将弹出框插入至 body 元素 当弹出框的位置出现问题时,你可以尝试将该属性设置为false。boolean-false
teleported该下拉菜单是否使用teleport插入body元素booleantrue / falsetrue
persistent当下拉选择器未被激活并且persistent设置为false,选择器会被删除。booleantrue / falsetrue
popper-options自定义 popper 选项,更多请参考 popper.js Virtualized Select 虚拟化选择器 - 图13object--
automatic-dropdown对于不可过滤的 Select 组件,此属性决定是否在输入框获得焦点后自动弹出选项菜单boolean-false
height下拉菜单的高度,每一个子选项的高度是 34pxnumber-170
scrollbar-always-on控制是否总是展示滚动条boolean-false
remote是否从服务器搜索数据booleanfalse
remote-method当输入值发生变化时被调用的函数。 其参数是当前输入值。 只有当 filterable 设置为 true 时才会生效。function(keyword: string)
validate-event输入时是否触发表单的校验boolean-true

SelectV2 事件

事件名说明回调参数
change选中值发生变化时触发val,目前的选中值
visible-change下拉框出现/隐藏时触发val,出现则为 true,隐藏则为 false
remove-tag多选模式下移除tag时触发val,移除的tag值
clear可清空的单选模式下用户点击清空按钮时触发
blur当选择器的输入框失去焦点时触发(event: Event)
focus当选择器的输入框获得焦点时触发(event: Event)

SelectV2 插槽

插槽名说明
default自定义 Option 模板
empty自定义当选项为空时的内容
prefix输入框的前缀

源代码

组件 Virtualized Select 虚拟化选择器 - 图14 文档 Virtualized Select 虚拟化选择器 - 图15

贡献者

Virtualized Select 虚拟化选择器 - 图16 云游君

Virtualized Select 虚拟化选择器 - 图17 三咲智子

Virtualized Select 虚拟化选择器 - 图18 Jeremy

Virtualized Select 虚拟化选择器 - 图19 msidolphin

Virtualized Select 虚拟化选择器 - 图20 Alan Wang

Virtualized Select 虚拟化选择器 - 图21 Xc

Virtualized Select 虚拟化选择器 - 图22 btea

Virtualized Select 虚拟化选择器 - 图23 Aex

Virtualized Select 虚拟化选择器 - 图24 Delyan Haralanov

Virtualized Select 虚拟化选择器 - 图25 Herrington Darkholme

Virtualized Select 虚拟化选择器 - 图26 zz

Virtualized Select 虚拟化选择器 - 图27 Carter Li

Virtualized Select 虚拟化选择器 - 图28 joson

Virtualized Select 虚拟化选择器 - 图29 kooriookami

Virtualized Select 虚拟化选择器 - 图30 sechi

Virtualized Select 虚拟化选择器 - 图31 ashun

Virtualized Select 虚拟化选择器 - 图32 Hefty

Virtualized Select 虚拟化选择器 - 图33 Cheerwhy

Virtualized Select 虚拟化选择器 - 图34 白雾三语

Virtualized Select 虚拟化选择器 - 图35 BeADre

Virtualized Select 虚拟化选择器 - 图36 bqy

Virtualized Select 虚拟化选择器 - 图37 Ryan2128

Virtualized Select 虚拟化选择器 - 图38 spx

Virtualized Select 虚拟化选择器 - 图39 weidehai

Virtualized Select 虚拟化选择器 - 图40 啝裳

Virtualized Select 虚拟化选择器 - 图41 Dreamcreative

Virtualized Select 虚拟化选择器 - 图42 C.Y.Kun

Virtualized Select 虚拟化选择器 - 图43 LinZhanMing

Virtualized Select 虚拟化选择器 - 图44 qiang

Virtualized Select 虚拟化选择器 - 图45 Yorn Qiu

Virtualized Select 虚拟化选择器 - 图46 Calum Knott