Vue3+ElementPlus实例_select选择器(不连续搜索)

发布时间:2024年01月16日

1.开发需求

在各大UI框架的select选择器中,在搜索时都是输入连续的搜索内容,比如“app-store”选项,你要输入“app-xxx”,才能匹配这个选择,要是想输入“a-s”这种不连续的匹配方式,就实现不了,用户体验较差,所以就开发了一个不连续搜索的select选择器,并带有输入内容的高亮提示。

2.实现演示

下面是我完成后的演示,请看

3.主要难点

? ? ? ? 1.如何不连续匹配选项

? ? ? ? 这里我们借用了一下第三方的api库——sdm2

? ? ? ? 2.匹配的代码逻辑??

?我这里做成了通用组件的模式:

点个赞呗~

4.代码

? ? ? ? 子组件代码

<template>
  <!-- 非连续搜索下拉组件 -->
  <el-select v-model="value" :clearable="clearable" filterable placeholder="请选择" :filter-method="(q) => (query = q)"
    @change="selectChange">
    <el-option v-for="item in filteredOptions" :key="item.value" :label="item.label" :value="item.value">
      <div v-if="props.isHigh" v-html="item.highlight"></div>
    </el-option>
  </el-select>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";
import { match, filterMap } from "sdm2";

const props = defineProps({
  selectValue: { type: String, default: '' }, //选中值
  clearable: { type: Boolean, default: true }, //是否可清除
  options: { type: Array<any>, default: [] },//选项
  isHigh: { type: Boolean, default: false }, //是否高亮
  highlightColor: { type: String, default: 'red' },//高亮颜色
});
const query = ref("");
const value = ref(props.selectValue);
const emits = defineEmits(["update:selectValue"]);

// 格式化选项
const filteredOptions = computed(() => {
  if (!props.isHigh) {
    let optionsList = props.options.filter(({ label }) =>
      // 使用sdm2的match函数筛选
      match(label, query.value, {
        // 忽略大小写匹配
        ignoreCase: true,
      })
    )
    return optionsList;
  } else {
    let optionsList = filterMap(props.options, query.value, {
      // 忽略大小写匹配
      ignoreCase: true,
      // 把matchStr返回的字符串作为被匹配项
      matchStr: ({ label }) => label,
      // 匹配到后转换为html高亮字符串
      onMatched: (matchedStr) =>
        `<span style="color:${props.highlightColor}" class="highlight">${matchedStr}</span>`,
      // 将匹配到的项转换为所需要的格式,str为onMatched转换后的字符串,origin为原始项
      onMap: ({ str, origin }) => {
        return {
          highlight: str,
          ...origin,
        };
      },
    })
    return optionsList;
  }
}
);
// 选中值
function selectChange() {
  emits("update:selectValue", value.value);
}
</script>
<style lang="less" scoped></style>

父组件代码:

<template>
  <!-- 非连续下拉搜索框 -->
  <div class="discontinuous-select">
    <span>高亮颜色 </span>
    <el-color-picker v-model="highlightColor" />
    <p></p>
    <span>是否高亮 </span>
    <el-radio-group v-model="isHigh">
      <el-radio :label="true">是</el-radio>
      <el-radio :label="false">否</el-radio>
    </el-radio-group>
    <p></p>
    <span>组件模式 </span>
    <DisSelect v-model:selectValue="selectValue" :options="options" :isHigh="isHigh" :highlightColor="highlightColor">
    </DisSelect>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue";
import DisSelect from './components/DisSelect.vue'
const options = ref([
  {
    label: "Apple",
    value: "apple",
  },
  {
    label: "Banana",
    value: "banana",
  },
  {
    label: "Fig",
    value: "fig",
  },
  {
    label: "Grape",
    value: "grape",
  },
  {
    label: "Lemon",
    value: "lemon",
  },
  {
    label: "Mango",
    value: "mango",
  },
  {
    label: "Orange",
    value: "orange",
  },
  {
    label: "Pineapple",
    value: "pineapple",
  },
]);

// 组件模式
const selectValue = ref("");
// 高亮颜色
const highlightColor = ref('#FF0000')
// 是否高亮
const isHigh = ref(true);
watch((selectValue), (newVal, oldVal) =>
  console.log("selectValue", newVal)
);
</script>
<style lang="less" scoped>
.discontinuous-select {
  height: 100%;
  width: 100%;
  text-align: center;
}
</style>

点个赞呗~

文章来源:https://blog.csdn.net/qq_40601005/article/details/135627153
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。