Select 下拉选择框

下拉选择框用来在较多的选项中选择一项或多项。如果选项数量少于 5 ,建议使用 单选框多选框 组件。

基本用法

使用 options 属性指定所有的选项,v-model 绑定用户选择的值。

请选择...
<c-select
  v-model="dim"
  :options="options"
/>
<span v-if="dim">您选择的是 {{ dim }}</span>

<script>
export default {
  data () {
    return {
      dim: '',
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv' },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv' },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  }
}
</script>

弹出选项是否覆盖

select 组件触发后,弹出的选项默认会覆盖在选择框上。但有时候产品并不想要这种效果。这时候可以通过shouldMenuOverlap 属性(should-menu-overlap)加以调整。下面分别是两种不同的效果:

请选择...
请选择...
<c-select v-model="dim" :options="options" />
<c-select v-model="dim" :options="options" :should-menu-overlap="false" />

<script>
export default {
  data () {
    return {
      dim: '',
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv' },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv' },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  }
}
</script>

多选

c-select 添加 multiple 属性可以将其设置为多选。在多选时,v-model 绑定的值是一个数组。

浏览量
新访客数
您选择的是 [ "pv", "nv" ]
<c-select
  v-model="dim"
  :options="options"
  width="longer"
  :maxChipCount="2"
  :maxChipPlaceholder="getChipPlaceholder"
  multiple
/>

<span v-if="dim">您选择的是 {{ dim }}</span>

<script>
export default {
  data () {
    return {
      dim: ['pv', 'nv'],
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv' },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv' },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  },
  methods: {
     getChipPlaceholder (omittedCount) {
       return `和另外${omittedCount}个选项`
    }
  }
}
</script>

禁用状态

禁用某些选项

options 数组中的项添加 disabled 属性可将该选项禁用。

浏览量
新访客数
您选择的是 [ "pv", "nv" ]
<c-select
  v-model="dim"
  :options="options"
  width="long"
  multiple
/>

<span v-if="dim">您选择的是 {{ dim }}</span>

<script>
export default {
  data () {
    return {
      dim: ['pv', 'nv'],
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv', disabled: true },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv', disabled: true },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  }
}
</script>

禁用整个下拉框

c-select 添加 disabled 属性将整个下拉框禁用。

浏览量
您选择的是 pv
<c-select
  v-model="dim"
  :options="options"
  disabled
/>

<span v-if="dim">您选择的是 {{ dim }}</span>

<script>
export default {
  data () {
    return {
      dim: 'pv',
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv' },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv' },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  }
}
</script>

不同尺寸的下拉框

size 属性控制输入框的整体大小。

IP 数
IP 数
IP 数
IP 数
IP 数
IP 数
IP 数
IP 数
IP 数
IP 数
<div class="has-margin-bottom-md" v-for="size in ['xs', 'sm', 'md', 'lg', 'xl']">
  <c-select v-model="dim" :options="options" :size="size" />
  <c-select v-model="dim2" multiple :options="options" :size="size" />
  <c-button primary :size="size">按钮</c-button>
</div>

<script>
export default {
  data () {
    return {
      dim: 'ip',
      dim2: ['ip'],
      options: [
        { label: '浏览量', value: 'pv' },
        { label: '访客数', value: 'uv' },
        { label: '新访客数', value: 'nv' },
        { label: '访问时长', value: 'du' },
        { label: '转化次数', value: 'cv' },
        { label: 'IP 数', value: 'ip' }
      ]
    }
  }
}
</script>

输入框宽度

使用 width 属性控制输入框的长度。Clair 中的下拉选择狂默认宽度为 15em,你可以通过 width 属性设置不同宽度的输入框。在下面的例子中,你可以选择不同的 sizewidth 查看宽高的大小:

请选择...

自定义展示

通过 Vue.js 的 Scoped Slots 特性,我们可以写一个模版替换内置的菜单项展示。

请选择...
<template>
  <c-select
    v-model="device"
    :options="options"
  >
    <template
      slot="menu-item"
      slot-scope="menuItem"
      scope="menuItem"
    >
      <c-icon :name="menuItem.option.icon" />
      <span>{{ menuItem.label }}</span>
    </template>
  </c-select>
</template>

<script>
export default {
  data () {
    return {
      device: '',
      options: [
        { label: '打印机', icon: 'printer', value: 1 },
        { label: '显示器', icon: 'monitor', value: 2 },
        { label: '智能手机', icon: 'smartphone', value: 3 },
        { label: 'CPU', icon: 'cpu', value: 4 },
        { label: '头戴式耳机', icon: 'headphones', value: 5 },
        { label: '数码相机', icon: 'camera', value: 6 }
      ]
    }
  }
}
</script>

<style>
.c-icon {
  vertical-align: middle;
  margin-right: 0.4em;
}
</style>

使用类似的方式,也可以实现对已选内容的自定义:

<template>
  <c-select
    v-model="device"
    :options="options"
    width="long"
    multiple
  >
    <template
      slot="selection"
      slot-scope="data"
      scope="data"
    >
      <c-icon :name="data.option.icon" />
    </template>
  </c-select>
</template>

<script>
export default {
  data () {
    return {
      device: [1, 2, 3],
      options: [
        { label: '打印机', icon: 'printer', value: 1 },
        { label: '显示器', icon: 'monitor', value: 2 },
        { label: '智能手机', icon: 'smartphone', value: 3 },
        { label: 'CPU', icon: 'cpu', value: 4 },
        { label: '头戴式耳机', icon: 'headphones', value: 5 },
        { label: '数码相机', icon: 'camera', value: 6 }
      ]
    }
  }
}
</script>

<style>
.c-icon {
  vertical-align: middle;
  margin-right: 0.4em;
}
</style>

选项筛选

c-select 设置 autocomplete 属性可以允许用户输入筛选条件对选项进行过滤。

默认情况下,搜索规则是将用户输入和每个选项的 label 进行匹配,大小写不敏感。如果你想自定义过滤规则,可以通过 filter 属性传入一个过滤函数。

请选择...
<c-select
  v-model="state"
  :options="options"
  :filter="filter"
  autocomplete
/>

<script>
const options = [
  { "label": "Alabama", "value": "al" },
  { "label": "Alaska", "value": "ak" },
  { "label": "Arizona", "value": "az" },
  { "label": "Arkansas", "value": "ar" },
  { "label": "California", "value": "ca" },
  { "label": "Colorado", "value": "co" },
  { "label": "Connecticut", "value": "ct" },
  { "label": "Delaware", "value": "de" },
  { "label": "Florida", "value": "fl" },
  { "label": "Georgia", "value": "ga" },
  { "label": "Hawaii", "value": "hi" },
  { "label": "Idaho", "value": "id" },
  { "label": "Illinois", "value": "il" },
  { "label": "Indiana", "value": "in" },
  { "label": "Iowa", "value": "ia" },
  { "label": "Kansas", "value": "ks" },
  { "label": "Kentucky", "value": "ky" },
  { "label": "Louisiana", "value": "la" },
  { "label": "Maine", "value": "me" },
  { "label": "Maryland", "value": "md" },
  { "label": "Massachusetts", "value": "ma" },
  { "label": "Michigan", "value": "mi" },
  { "label": "Minnesota", "value": "mn" },
  { "label": "Mississippi", "value": "ms" },
  { "label": "Missouri", "value": "mo" },
  { "label": "Montana", "value": "mt" },
  { "label": "Nebraska", "value": "ne" },
  { "label": "Nevada", "value": "nv" },
  { "label": "New Hampshire", "value": "nh" },
  { "label": "New Jersey", "value": "nj" },
  { "label": "New Mexico", "value": "nm" },
  { "label": "New York", "value": "ny" },
  { "label": "North Carolina", "value": "nc" },
  { "label": "North Dakota", "value": "nd" },
  { "label": "Ohio", "value": "oh" },
  { "label": "Oklahoma", "value": "ok" },
  { "label": "Oregon", "value": "or" },
  { "label": "Pennsylvania", "value": "pa" },
  { "label": "Rhode Island", "value": "ri" },
  { "label": "South Carolina", "value": "sc" },
  { "label": "South Dakota", "value": "sd" },
  { "label": "Tennessee", "value": "tn" },
  { "label": "Texas", "value": "tx" },
  { "label": "Utah", "value": "ut" },
  { "label": "Vermont", "value": "vt" },
  { "label": "Virginia", "value": "va" },
  { "label": "Washington", "value": "wa" },
  { "label": "West Virginia", "value": "wv" },
  { "label": "Wisconsin", "value": "wi" },
  { "label": "Wyoming", "value": "wy" }
]

export default {
  data () {
    return {
      state: '',
      options,
      // 如果需要,可以自定义过滤函数
      // filter: (option, query) => option.label.includes(query)
    }
  }
}
</script>

对于可以多选的下拉框,也可以让用户过滤选项。

请选择...
<c-select
  v-model="state"
  :options="options"
  width="long"
  multiple
  autocomplete
/>

<script>
const options = [
  { "label": "Alabama", "value": "al" },
  { "label": "Alaska", "value": "ak" },
  { "label": "Arizona", "value": "az" },
  { "label": "Arkansas", "value": "ar" },
  { "label": "California", "value": "ca" },
  { "label": "Colorado", "value": "co" },
  { "label": "Connecticut", "value": "ct" },
  { "label": "Delaware", "value": "de" },
  { "label": "Florida", "value": "fl" },
  { "label": "Georgia", "value": "ga" },
  { "label": "Hawaii", "value": "hi" },
  { "label": "Idaho", "value": "id" },
  { "label": "Illinois", "value": "il" },
  { "label": "Indiana", "value": "in" },
  { "label": "Iowa", "value": "ia" },
  { "label": "Kansas", "value": "ks" },
  { "label": "Kentucky", "value": "ky" },
  { "label": "Louisiana", "value": "la" },
  { "label": "Maine", "value": "me" },
  { "label": "Maryland", "value": "md" },
  { "label": "Massachusetts", "value": "ma" },
  { "label": "Michigan", "value": "mi" },
  { "label": "Minnesota", "value": "mn" },
  { "label": "Mississippi", "value": "ms" },
  { "label": "Missouri", "value": "mo" },
  { "label": "Montana", "value": "mt" },
  { "label": "Nebraska", "value": "ne" },
  { "label": "Nevada", "value": "nv" },
  { "label": "New Hampshire", "value": "nh" },
  { "label": "New Jersey", "value": "nj" },
  { "label": "New Mexico", "value": "nm" },
  { "label": "New York", "value": "ny" },
  { "label": "North Carolina", "value": "nc" },
  { "label": "North Dakota", "value": "nd" },
  { "label": "Ohio", "value": "oh" },
  { "label": "Oklahoma", "value": "ok" },
  { "label": "Oregon", "value": "or" },
  { "label": "Pennsylvania", "value": "pa" },
  { "label": "Rhode Island", "value": "ri" },
  { "label": "South Carolina", "value": "sc" },
  { "label": "South Dakota", "value": "sd" },
  { "label": "Tennessee", "value": "tn" },
  { "label": "Texas", "value": "tx" },
  { "label": "Utah", "value": "ut" },
  { "label": "Vermont", "value": "vt" },
  { "label": "Virginia", "value": "va" },
  { "label": "Washington", "value": "wa" },
  { "label": "West Virginia", "value": "wv" },
  { "label": "Wisconsin", "value": "wi" },
  { "label": "Wyoming", "value": "wy" }
]

export default {
  data () {
    return {
      state: [],
      options
    }
  }
}
</script>

异步搜索

某些场景下,你会需要根据用户的输入从服务器端获取相关选项。你可以指定 filter 函数返回一个 Promise 即可。使用 filter 函数时,可以通过 filterThrottle 指定最小触发间隔,其默认值为 0

请选择...
<c-select
  v-model="choice"
  :options="options"
  :filter="search"
  :filterThrottle="1000"
  autocomplete
  multiple
>
</c-select>

<script>
const rdn = _ => Math.random().toString(36).substr(-3)
const defaultOptions = ['option 1', 'option 2', 'option 3']
  .map(value => ({label: value, value}))
export default {
  data () {
    return {
      choice: '',
      options: []
    }
  },
  methods: {
    search (options, query) {
      console.log('filter called with query: ', query)
      if (!query) return defaultOptions
      return new window.Promise((resolve, reject) => {
        setTimeout(_ => {
          resolve([1, 2, 3].map(i => `${query}-${rdn()}`))
        }, Math.random() * 1000)
      })
    }
  }
}
</script>

与模态框结合

<c-button primary @click="visible = true">点我!</c-button>

<c-modal
  width="420px"
  :visible="visible"
  @close="visible = false"
>
  <div slot="header">选择指标</div>
  <c-select
    v-model="dim"
    :options="options"
  />
</c-modal>

<script>
  export default {
    data () {
      return {
        visible: false,
        dim: '',
        options: [
          { label: '浏览量', value: 'pv' },
          { label: '访客数', value: 'uv' },
          { label: '新访客数', value: 'nv' },
          { label: '访问时长', value: 'du' },
          { label: '转化次数', value: 'cv' },
          { label: 'IP 数', value: 'ip' }
        ]
      }
    },
    methods: {}
  }
</script>

API

属性

属性 类型 默认值 说明
options Array 选项列表
disabled Boolean false 下拉框是否被禁用
placeholder String '请选择...' 未进行选择时的提示
multiple Boolean false 是否允许多选
autocomplete Boolean false 是否允许用户对选项进行搜索
filter Function 按label过滤 自定义对选项过滤函数,异步时可返回 Promise
filterThrottle Number 0 调用 filter 函数的最短间隔
maxChipCount Number Infinity 多选时最多展示多少个选中的选项
maxChipPlaceholder String Function

slots

名称 是否 Scoped 说明
menu-item 自定义下拉菜单项的展示,scope 为菜单项的数据
no-match 自定义无法找到用户搜索的选项时的提示