[sgAutocomplete] Custom component: An auto-complete drop-down box component developed based on elementUI's el-autocomplete component (auto-complete input box with input suggestions)

d4f50ad8f5e54f549e447d0a0a6c694f.gif

characteristic:

1. Support local saving of selected records

2. Support dynamic interface to obtain matching drop-down box content

3. You can specify the corresponding display label and field component key

4. Automatically generate shorthand fields (including initial consonants and full spelling types) to enhance search and matching efficiency

sgAutocomplete source code

<template>
  <!-- 基于elementUIel-autocomplete组件开发的自动补全下拉框组件 -->
  <el-autocomplete
    :class="$options.name"
    style="width: 100%"
    ref="autocomplete"
    :popper-class="'sgAutocomplete-el-autocomplete'"
    v-model="inputSearchValue"
    :placeholder="placeholder || `输入关键词…`"
    :value-key="valueKey || `label`"
    :fetch-suggestions="fetchSuggestions"
    :hide-loading="false"
    @focus="$refs.autocomplete.$el.querySelector('input').select()"
    @select="selectSuggestionsItem"
    @clear="focusAutocomplete"
    :debounce="0"
    clearable
  >
    <template slot-scope="{ item }">
      <div>
        <i v-if="item.isHistory" class="history-icon el-icon-time" />
        <span class="label">{
   
   { item[labelKey || `label`] }}</span>
      </div>
    </template>

    <!-- 搜索按钮1 -->
    <i class="el-icon-search el-input__icon" slot="suffix" v-if="showSearchButton == 1" />

    <!-- 删除历史记录按钮 -->
    <i
      :title="clearHistoryTitle || `删除历史记录`"
      class="el-icon-delete el-input__icon clearHistory"
      slot="suffix"
      v-if="showHistoryBtn"
      @click="clearHistory"
    />

    <!-- 搜索按钮2 -->
    <el-button
      slot="append"
      icon="el-icon-search"
      @click="focusAutocomplete"
      v-if="showSearchButton == 2"
    ></el-button>
  </el-autocomplete>
</template>

<script>
import pinyin from "@/js/pinyin";
export default {
  name: "sgAutocomplete",
  components: {},
  data() {
    return {
      inputSearchValue: null,
      historyListLocalStorageName: null, //保存到本地记录的localStorage Key
      searchItems: [],
      showHistoryBtn: false,
    };
  },
  props: [
    "data", //可选项数组(必选参数)
    "value",
    "valueKey", //获取值
    "labelKey", //显示值
    "placeholder",
    "clearHistoryTitle", //删除历史记录按钮提示
    "filterKeys", //匹配搜索的字段(数组)不传此参数默认就用labelKey
    "showHistory", //显示历史选择记录
    "showSearchButton", //显示搜索按钮(样式:1 是在输入框里面的icon,2 是在输入框后面的按钮)
    "autofocus",
  ],
  watch: {
    data: {
      handler(newValue, oldValue) {
        if (newValue && Object.keys(newValue).length) {
          this.searchItems = JSON.parse(JSON.stringify(newValue));
          this.searchItems.forEach((v) => {
            v.SJF = pinyin.getCamelChars(v[this.labelKey || "label"]); //速记符(声母)
            v.SJF_full = pinyin.getFullChars(v[this.labelKey || "label"]); //速记符(全拼)
          });
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
    value: {
      handler(newValue, oldValue) {
        this.inputSearchValue = newValue;
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
    inputSearchValue: {
      handler(newValue, oldValue) {
        this.$emit(`input`, newValue);
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
    showHistory: {
      handler(newValue, oldValue) {
        this.historyListLocalStorageName = newValue;
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  mounted() {
    (this.autofocus === "" || this.autofocus) && this.focusAutocomplete(); //默认聚焦
  },
  methods: {
    focusAutocomplete(d) {
      this.$nextTick(() => {
        this.$refs.autocomplete.focus();
        this.$refs.autocomplete.activated = true; //这句话是重点
      });
    },
    // 搜索下拉框
    fetchSuggestions(queryString, callback) {
      if (queryString) {
        queryString = queryString.toString().trim();
        let r = this.searchItems.filter((v, i, ar) => {
          let filterKeys = this.filterKeys || [this.labelKey];
          filterKeys.push("SJF", "SJF_full"); //自动匹配声母、全屏组合
          return filterKeys.some((filterKey) =>
            v[filterKey].toLocaleLowerCase().includes(queryString.toLocaleLowerCase())
          );
        });
        this.showHistoryBtn = false;
        callback(r);
      } else {
        let historys = this.getHistorys();
        historys.forEach((v) => (v.isHistory = true)); //标识是历史记录
        this.showHistoryBtn = historys.length > 0;
        callback(historys);
      }
    },
    selectSuggestionsItem(d) {
      let historys = this.getHistorys();
      if (historys.length) {
        let k = this.valueKey || this.labelKey || "label";
        let has = historys.some((v) => v[k] == d[k]);
        has || historys.unshift(d);
        localStorage[this.historyListLocalStorageName] = JSON.stringify(historys);
      } else {
        localStorage[this.historyListLocalStorageName] = JSON.stringify([d]);
      }
      this.$emit(`change`, d);
    },
    getHistorys() {
      let historys = localStorage[this.historyListLocalStorageName];
      return JSON.parse(historys || "[]");
    },
    clearHistory(d) {
      delete localStorage[this.historyListLocalStorageName];
      this.showHistoryBtn = false;
      this.focusAutocomplete();
    },
  },
};
</script>

<style lang="scss" scoped>
.sgAutocomplete {
  .clearHistory {
    cursor: pointer;
    &:hover {
      color: #409eff;
    }
  }
}
</style>

The pinyin.js used in it is in this articleJS automatically generates shorthand symbols, pinyin abbreviations/initial consonants of Pinyin (for example: "Your beloved Brother Qiang" is converted into "NZADQG"). Extract the first letter and return the capital form; extract pinyin and return the first letter in capital form (full pinyin). _Your beloved Brother Qiang’s blog-CSDN BlogThe article has been viewed and read 2.7k times. The following pinyin.js file needs to be referenced. https://blog.csdn.net/qq_37860634/article/details/130765296

Example

<template>
  <div>
    <sgAutocomplete
      autofocus
      v-model="sgAutocompleteValue"
      :data="data"
      :placeholder="`输入搜索关键词...`"
      :valueKey="`value`"
      :labelKey="`label`"
      showHistory="localStorageHistoryName"
      showSearchButton="2"
      @change="changeSgAutocomplete"
    />

    <p style="margin-top: 20px">选择的数据:{
   
   { sgAutocompleteValue }}</p>
    <p
      style="
        margin-top: 20px;
        word-wrap: break-word;
        word-break: break-all;
        white-space: break-spaces;
      "
    >
      <span>选择的对象:</span>
      {
   
   { sgAutocompleteObject ? JSON.stringify(sgAutocompleteObject, null, 2) : "" }}
    </p>
  </div>
</template>
<script>
import sgAutocomplete from "@/vue/components/admin/sgAutocomplete";
export default {
  components: { sgAutocomplete },
  data() {
    return {
      sgAutocompleteValue: null,
      sgAutocompleteObject: null,
      data: [],
      //模拟数据1
      dataA: [
        { value: "1", label: "A显示文本1" },
        { value: "2", label: "A显示文本2" },
        { value: "3", label: "A显示文本3" },
        { value: "4", label: "A显示文本4" },
        { value: "5", label: "A显示文本5" },
      ],
      //模拟数据2
      dataB: [
        { value: "1", label: "B显示文本1" },
        { value: "2", label: "B显示文本2" },
        { value: "3", label: "B显示文本3" },
        { value: "4", label: "B显示文本4" },
        { value: "5", label: "B显示文本5" },
      ],
    };
  },
  watch: {
    // 模拟动态更新筛选项
    sgAutocompleteValue: {
      handler(newValue, oldValue) {
        if (newValue && Object.keys(newValue).length) {
          switch (newValue.toLocaleLowerCase()) {
            case "a":
              this.data = this.dataA;
              break;
            case "b":
              this.data = this.dataB;
              break;
          }
        }
      },
    },
  },
  methods: {
    changeSgAutocomplete(d) {
      this.sgAutocompleteObject = d;
    },
  },
};
</script>

 

 

Guess you like

Origin blog.csdn.net/qq_37860634/article/details/134851806