# BySelect 选择器组件

基于 Element UI Select 的高级选择器组件,提供数据选择、远程搜索、异步加载、分组选项等功能。

注意:本组件基于 Element UI Select 实现,支持 Element UI Select 的所有功能。如需了解更多高级配置和功能,请参考 Element UI Select 官方文档 (opens new window)

# 基础用法

<template>
  <by-select v-model="value" :options="options" :config="config" placeholder="请选择" />
</template>

<script>
export default {
  data() {
    return {
      value: '',
      options: [
        { label: '选项1', value: 'option1' },
        { label: '选项2', value: 'option2' },
        { label: '选项3', value: 'option3' }
      ],
      config: {
        placeholder: '请选择',
        optionLabel: 'label',
        optionValue: 'value'
      }
    }
  }
}
</script>

# 高级功能

# 1. 多选模式

支持多选模式,可以选择多个选项。

<template>
  <by-select v-model="multiValue" :options="options" multiple placeholder="请选择多个选项" />
</template>

<script>
export default {
  data() {
    return {
      multiValue: [],
      options: [
        { label: '选项一', value: 'option1' },
        { label: '选项二', value: 'option2' },
        { label: '选项三', value: 'option3' },
        { label: '选项四', value: 'option4' }
      ]
    }
  }
}
</script>

特性:

  • 支持选择多个选项
  • 自动处理多选数据格式
  • 支持标签移除功能
  • 解决多选时选择后下拉数据重置问题

# 2. 远程搜索

支持远程搜索数据,适用于大数据量场景。

<template>
  <by-select
    v-model="remoteValue"
    :options="remoteOptions"
    :remote="true"
    :loading="loading"
    @search="handleRemoteSearch"
    placeholder="请输入关键字搜索"
  />
</template>

<script>
export default {
  data() {
    return {
      remoteValue: '',
      remoteOptions: [],
      loading: false
    }
  },
  methods: {
    async handleRemoteSearch(query) {
      if (query) {
        this.loading = true
        try {
          // 模拟远程搜索
          const { data } = await this.$http.get('/api/search', {
            params: { keyword: query }
          })
          this.remoteOptions = data.map(item => ({
            label: item.name,
            value: item.id
          }))
        } catch (error) {
          console.error(error)
        } finally {
          this.loading = false
        }
      } else {
        this.remoteOptions = []
      }
    }
  }
}
</script>

特性:

  • 支持远程数据搜索
  • 自动处理加载状态
  • 支持搜索防抖
  • 优化用户体验

# 3. 异步加载选项

支持异步加载选项数据,适用于动态数据场景。

<template>
  <by-select v-model="asyncValue" :load-options="loadOptions" :auto-load="true" :config="config" placeholder="请选择" />
</template>

<script>
export default {
  data() {
    return {
      asyncValue: '',
      config: {
        optionLabel: 'name',
        optionValue: 'id'
      }
    }
  },
  methods: {
    async loadOptions() {
      // 模拟异步加载数据
      const { data } = await this.$http.get('/api/options')
      return data
    }
  }
}
</script>

特性:

  • 支持组件挂载时自动加载
  • 支持手动刷新数据
  • 支持展开时重新加载
  • 自动处理加载状态

# 4. 分组选项

支持选项分组显示,适用于分类数据展示。

<template>
  <by-select v-model="groupValue" :options="groupOptions" :config="groupConfig" placeholder="请选择" />
</template>

<script>
export default {
  data() {
    return {
      groupValue: '',
      groupOptions: [
        {
          label: '热门城市',
          options: [
            { label: '北京', value: 'beijing' },
            { label: '上海', value: 'shanghai' }
          ]
        },
        {
          label: '其他城市',
          options: [
            { label: '深圳', value: 'shenzhen' },
            { label: '广州', value: 'guangzhou' }
          ]
        }
      ],
      groupConfig: {
        mode: 'group',
        optionLabel: 'label',
        optionValue: 'value'
      }
    }
  }
}
</script>

特性:

  • 支持多级分组显示
  • 灵活的分组数据结构
  • 保持所有选择功能
  • 支持分组标签自定义

# 5. 可清空选择

支持清空已选择的选项。

<template>
  <by-select v-model="clearableValue" :options="options" clearable placeholder="请选择(可清空)" />
</template>

<script>
export default {
  data() {
    return {
      clearableValue: '',
      options: [
        { label: '选项1', value: 'option1' },
        { label: '选项2', value: 'option2' }
      ]
    }
  }
}
</script>

特性:

  • 支持清空已选择的值
  • 提供清空按钮
  • 触发清空事件
  • 提升用户体验

# 6. 禁用状态

支持禁用选择器,适用于权限控制场景。

<template>
  <by-select v-model="disabledValue" :options="options" :disabled="true" placeholder="禁用状态" />
</template>

<script>
export default {
  data() {
    return {
      disabledValue: '',
      options: [
        { label: '选项1', value: 'option1' },
        { label: '选项2', value: 'option2' }
      ]
    }
  }
}
</script>

特性:

  • 支持整体禁用
  • 适用于权限控制
  • 防止用户误操作
  • 清晰的视觉反馈

# 7. 自定义配置

支持灵活的数据字段配置,适配不同的数据结构。

<template>
  <by-select v-model="customValue" :options="customOptions" :config="customConfig" placeholder="请选择" />
</template>

<script>
export default {
  data() {
    return {
      customValue: '',
      customOptions: [
        { name: '用户1', id: 1 },
        { name: '用户2', id: 2 }
      ],
      customConfig: {
        optionLabel: 'name', // 自定义标签字段
        optionValue: 'id', // 自定义值字段
        placeholder: '请选择用户'
      }
    }
  }
}
</script>

特性:

  • 支持自定义字段映射
  • 适配不同数据结构
  • 灵活的配置选项
  • 提升组件复用性

# API

# Props

参数 说明 类型 默认值
value 绑定值 String/Number/Array ''
options 选项数据 Array []
config 配置对象 Object {}
placeholder 占位符 String 请选择
loadOptions 异步加载选项函数 Function null
autoLoad 是否自动加载 Boolean true
multiple 是否多选 Boolean false
remote 是否远程搜索 Boolean false
clearable 是否可清空 Boolean false
disabled 是否禁用 Boolean false
loading 是否加载中 Boolean false

# Config 配置项

参数 说明 类型 默认值
placeholder 占位符文本 String 请选择
optionLabel 选项标签字段 String label
optionValue 选项值字段 String value
mode 模式类型 String -
refreshOnOpen 展开时是否刷新 Boolean false

# Events

事件名 说明 参数
change 选中值发生变化时触发 选中的值
visible-change 下拉框出现/隐藏时触发 出现则为true
remove-tag 多选模式下移除tag时触发 移除的tag值
clear 可清空的单选模式下用户点击清空按钮时触发
blur 当input失去焦点时触发 (event: Event)
focus 当input获得焦点时触发 (event: Event)
search 远程搜索时触发 搜索关键字
load-success 异步加载成功时触发 加载的数据
load-error 异步加载失败时触发 错误信息

# Methods

方法名 说明 参数
refresh 手动刷新数据 -

# 选项配置

参数 说明 类型 默认值
label 选项的标签,若不设置则默认与 value 相同 string/number
value 选项的值 string/number/object
disabled 是否禁用该选项 boolean false
options 分组时,该分组下的选项(分组模式时使用) array

# 完整示例

# 结合表单使用的完整示例

<template>
  <div>
    <el-form :model="form" label-width="100px">
      <el-form-item label="用户类型">
        <by-select v-model="form.userType" :options="userTypeOptions" placeholder="请选择用户类型" />
      </el-form-item>

      <el-form-item label="用户列表">
        <by-select
          v-model="form.users"
          :load-options="loadUserOptions"
          :config="userConfig"
          multiple
          placeholder="请选择用户"
        />
      </el-form-item>

      <el-form-item label="城市">
        <by-select v-model="form.city" :options="cityOptions" :config="cityConfig" clearable placeholder="请选择城市" />
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      form: {
        userType: '',
        users: [],
        city: ''
      },
      userTypeOptions: [
        { label: '管理员', value: 'admin' },
        { label: '普通用户', value: 'user' },
        { label: '访客', value: 'guest' }
      ],
      userConfig: {
        optionLabel: 'name',
        optionValue: 'id'
      },
      cityOptions: [
        {
          label: '一线城市',
          options: [
            { label: '北京', value: 'beijing' },
            { label: '上海', value: 'shanghai' }
          ]
        },
        {
          label: '二线城市',
          options: [
            { label: '杭州', value: 'hangzhou' },
            { label: '南京', value: 'nanjing' }
          ]
        }
      ],
      cityConfig: {
        mode: 'group',
        optionLabel: 'label',
        optionValue: 'value'
      }
    }
  },
  methods: {
    async loadUserOptions() {
      // 模拟异步加载用户数据
      const { data } = await this.$http.get('/api/users')
      return data
    }
  }
}
</script>

# 远程搜索示例

<template>
  <div>
    <by-select
      v-model="searchValue"
      :options="searchOptions"
      :remote="true"
      :loading="searchLoading"
      :config="searchConfig"
      filterable
      @search="handleSearch"
      placeholder="请输入关键字搜索"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      searchValue: '',
      searchOptions: [],
      searchLoading: false,
      searchConfig: {
        optionLabel: 'title',
        optionValue: 'id'
      }
    }
  },
  methods: {
    async handleSearch(query) {
      if (query) {
        this.searchLoading = true
        try {
          const { data } = await this.$http.get('/api/search', {
            params: { keyword: query }
          })
          this.searchOptions = data
        } catch (error) {
          console.error('搜索失败:', error)
        } finally {
          this.searchLoading = false
        }
      } else {
        this.searchOptions = []
      }
    }
  }
}
</script>

# 样式类

类名 说明
.by-select 选择器组件根容器
.by-select--disabled 禁用状态样式
.by-select--loading 加载状态样式
.by-select--multiple 多选模式样式

# 注意事项

  1. 数据格式:确保 options 数据格式正确,包含必要的 labelvalue 字段
  2. 异步加载:使用 loadOptions 时,确保函数返回正确的数据格式
  3. 远程搜索:启用远程搜索时,需要正确处理搜索逻辑和加载状态
  4. 分组模式:使用分组模式时,需要设置 config.mode = 'group'
  5. 字段映射:通过 config.optionLabelconfig.optionValue 自定义字段映射
  6. 多选处理:多选模式下,确保正确处理数组类型的数据
  7. 性能优化:大数据量时建议使用远程搜索或异步加载
  8. 事件处理:正确处理各种事件,特别是异步操作的成功和失败回调
最后更新时间: 6/23/2025, 5:49:10 PM