带历史记录自动补全输入框组件

143 阅读1分钟

该组件的由来是# 提升系统商品快速精准检索效率以满足业务部门快速下单需求

<template>
  <div class="input-container">
    <el-autocomplete
      v-model="inputValue"
      :fetch-suggestions="onFetchSuggestions"
      :placeholder="placeholder"
      popper-class="my-autocomplete"
      clearable
      @select="onSelect"
    >
      <template slot-scope="{ item }">
        <div class="el-autocomplete-suggestion-item">
          <span
            :title="item"
            class="name"
          >
            {{ item }}
          </span>
          <i
            class="el-icon-delete"
            @click.stop="deleteHistoryRecord(item)"
          />
        </div>
      </template>
    </el-autocomplete>
  </div>
</template>

<script>
export default {
  name: 'AutocompleteHistoryInput',
  props: {
    // 用于绑定的输入值
    value: {
      type: String,
      default: ''
    },
    // 存储历史记录的本地存储键名
    storageKey: {
      type: String,
      default: 'commonStorageKey'
    },
    // 输入历史记录数量上限
    historyLimit: {
      type: Number,
      default: 10
    },
    placeholder: {
      type: String,
      default: '请输入'
    }
  },
  data() {
    return {
      inputValue: this.value,
      inputHistory: []
    }
  },
  watch: {
    value(newValue) {
      this.inputValue = newValue
    },
    inputValue(newValue) {
      this.$emit('input', newValue)
    }
  },
  mounted() {
    this.loadHistory()
  },
  methods: {
    loadHistory() {
      const storedHistory = window.localStorage.getItem(this.storageKey)
      if (storedHistory) {
        this.inputHistory = JSON.parse(storedHistory)
      }
    },
    addToHistory(value) {
      if (value && !this.inputHistory.includes(value)) {
        this.inputHistory.push(value)
        if (this.inputHistory.length > this.historyLimit) {
          this.inputHistory.shift()
        }
        window.localStorage.setItem(
          this.storageKey,
          JSON.stringify(this.inputHistory)
        )
      }
    },
    onFetchSuggestions(queryString, cb) {
      let restaurants = this.inputHistory
      let results = queryString
        ? restaurants.filter(this.createFilter(queryString))
        : restaurants
      cb(results)
    },
    createFilter(queryString) {
      return restaurant => {
        return restaurant.toLowerCase().indexOf(queryString.toLowerCase()) === 0
      }
    },
    deleteHistoryRecord(historyItem) {
      const index = this.inputHistory.indexOf(historyItem)
      if (index !== -1) {
        this.inputHistory.splice(index, 1)
        window.localStorage.setItem(
          this.storageKey,
          JSON.stringify(this.inputHistory)
        )
      }
    },
    setInputLocalStorage() {
      this.addToHistory(this.inputValue)
    },
    onSelect(value) {
      this.inputValue = value
    }
  }
}
</script>

<style lang="scss" scoped>
.el-dropdown-link {
  cursor: pointer;
}

.el-icon-delete {
  margin-left: 5px;
  cursor: pointer;
  color: #999;
}
.el-autocomplete-suggestion-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  .name {
    display: inline-block;
    width: calc(100% - 24px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
</style>

在页面中使用:

<template>
  <autocomplete-history-input
   ref="inputComponent"
   v-model="formModel.name"
   :history-limit="10"
   storage-key="nameInputHistory"
 />
 <el-button @click="onSearch">查询</el-button>
</template>
<script>
import AutocompleteHistoryInput from '@/components/autocomplete-history-input.vue'
export default {
  data() {
    return {
      formModel:{
        name: ''
      }
    }
  },
  methods: {
    onSearch() {
      this.$refs.inputComponent.setInputLocalStorage()
      ...
    }
  }
}
</script>