技术选用:vue3
UI框架:element-plus
组件:Select 选择器
首先我们做的第一步就是要让select框允许输入并且支持帅选option,关于这部分element-plus已经为我们提供了现成的属性。
如果只设置filterable的话,那么筛选的时候只支持中文/英文的筛选,如果想要增加拼音联想的功能的话,我们要做的第一步是先将汉字转换成拼音,这里有很多成熟的npm包可以选用,这里我选择的是
首先安装
npm install pinyin-pro
在需要的页面进行导入
import {
pinyin } from 'pinyin-pro';
插件官方链接:https://github.com/zh-lx/pinyin-pro
简单使用方法:
import {
pinyin } from 'pinyin-pro';
// 获取带音调拼音
pinyin('汉语拼音'); // 'hàn yǔ pīn yīn'
// 获取数组形式带音调拼音
pinyin('汉语拼音', {
type: 'array' }); // ["hàn", "yǔ", "pīn", "yīn"]
// 获取数组形式不带声调的拼音
pinyin('汉语拼音', {
toneType: 'none', type: 'array' }); // ["han", "yu", "pin", "yin"]
// 获取带音调韵母
pinyin('汉语拼音', {
pattern: 'final' }); // 'àn ǔ īn īn'
有了以上方法后,并没有完结,我们会发现,在中文输入法开始输入的时候并不会自动触发筛选,这时候我们就需要另外一个属性的帮助
compositionupdate
compositionupdate这个方法在中文输入法更新但是还没确定的时候触发,对应的还有compositionend
:中文输入法结束,compositionstart
:中文输入法开始,而这里我们暂时只用到uopdate,有了这些准备后我们就可以实现我们想要的功能了,以下是一个小demo
<template>
<div >
<el-card shadow="hover">
<el-select
multiple
filterable
:filter-method="filterMethod"
@compositionupdate="handleCompositionUpdate"
style="width: 200px"
v-model="state.keyWord"
collapse-tags
collapse-tags-tooltip
>
<el-option v-for="(i, index) in state.option" :key="index" :label="i.label" :value="i.label"></el-option>
</el-select>
</el-card>
</div>
</template>
<script setup lang="ts" name="demo">
import { reactive, onMounted } from 'vue';
import { pinyin } from 'pinyin-pro';
const state = reactive<SysUserState>({
// 下拉菜单原始数据&真实使用的options
option: [],
list: [
{ label: '安信期货', value: '安信期货' },
{ label: '大地期货', value: '大地期货' },
{ label: '东证期货', value: '东证期货' },
{ label: '废钢期货', value: '废钢期货' },
{ label: '光大期货', value: '光大期货' },
{ label: '广发期货', value: '广发期货' },
{ label: '国泰期货', value: '国泰期货' },
{ label: '国债期货', value: '国债期货' },
{ label: '广州期货', value: '广州期货' },
{ label: '股指期货', value: '股指期货' },
{ label: '恒力期货', value: '恒力期货' },
{ label: '华泰期货', value: '华泰期货' },
{ label: '宏源期货', value: '宏源期货' },
{ label: '君安期货', value: '君安期货' },
{ label: '金瑞期货', value: '金瑞期货' },
{ label: '南华期货', value: '南华期货' },
{ label: '平安期货', value: '平安期货' },
{ label: '瑞达期货', value: '瑞达期货' },
{ label: '申万期货', value: '申万期货' },
{ label: '新湖期货', value: '新湖期货' },
{ label: '兴证期货', value: '兴证期货' },
{ label: '一德期货', value: '一德期货' },
{ label: '银河期货', value: '银河期货' },
{ label: '中粮期货', value: '中粮期货' },
{ label: '中泰期货', value: '中泰期货' },
{ label: '中信期货', value: '中信期货' },
{ label: '中州期货', value: '中州期货' },
],
// model
keyWord:[]
});
// 中文输入法更新时触发的操作
const handleCompositionUpdate = (e) => {
filterMethod(e.data.toString());
};
// 匹配首字母
const filterPinyin = (val: any, list: any) => {
return list.filter((item: any) => {
const arr = pinyin(`${item.value}`, { toneType: 'num', type: 'array' });
let str = '';
arr.forEach((item) => {
str = str + item.slice(0, 1);
});
// 汉字包含/ 首字母包含
if (item.value.includes(val) || str.toString().includes(val.toLowerCase())) {
return item;
}
});
};
// 筛选方法
const filterMethod = (val: any) => {
if (val) {
state.option = filterPinyin(val, state.list);
} else {
state.option = state.list;
}
};
// 页面加载时
onMounted(() => {
state.option = state.list;
});
</script>
<style scoped lang="scss">
</style>