【Vue.js】基於vue的實時搜索,在結果中高亮顯示關鍵詞


一、搜素效果如下:

 

二、核心

  1)利用oninput屬性來觸發搜素功能

  2)利用RegExp來對字符串來全局匹配關鍵字,利用replace方法來對匹配的關鍵字進行嵌入高亮的<span class="gaoliang">標簽,最后利用v-html來嵌入html標簽來達到關鍵字高亮顯示

  3)利用axios.CancelToken來終止上一次的異步請求,防止舊關鍵字查詢覆蓋新輸入的關鍵字查詢結果。

 

三、代碼

  1)HTML  搜索框部分綁定input事件(搜索框獨立出來,作為一個基礎組件(叫SearchToolbar.vue),嵌入到KnowledgeSearch.vue中)

<input type="text" class="input-search" placeholder="請輸入搜索內容" v-model.trim="searchKey" @input="searchEvent" ref="searchInput" autocomplete="off" autocapitalize="off" autocorrect="off"/>

 

  2)因為input綁定了輸入監聽事件@input,每一次輸入值的改變,都會觸發方法searchEvent(),尤其是在輸入搜索關鍵字的時候,這種情況必然發生發送多次http異步請求,這樣頻繁地請求會導致流量損耗與性能下降。

如何解決?

  我們利用setTimeout與clearTimeout元素,控制輸入間隔為500ms,如果超過500s還沒輸入任何東西,就會向后端發送http異步請求。例如在搜索框種輸入1,然后500ms過去之后,就會發送異步請求,如果在輸入1之后的500ms輸入值,例如我在499ms輸入了值‘2’,那么上一次關鍵字為1的異步請求就會取消,進而進行關鍵字為‘12’的異步請求,並等待500ms。代碼如下:

searchEvent() {
      this.clearTimer();
      if (this.searchKey && this.searchKey.length > 0) {
        //獲取當前延時函數的ID,便於后面clearTimeout清除該ID對應的延遲函數
        this.timer = setTimeout(() => {
          this.$emit('searchHandler', this.searchKey);
        }, 500);
      } else {
        this.$emit('searchHandler', this.searchKey);
      }
},

clearTimer() {
      if (this.timer) {
        clearTimeout(this.timer);
      }
}    

 

  注意,你仔細想想,這里還存在一個漏洞。根據關鍵字發送異步http請求,假如在網絡環境並不太好的情況下,異步請求可能經過2秒才返回關鍵字為‘成’的數據給我。然而,我在輸入完關鍵字‘成’,超過500ms之后在輸入‘龍’,那么之前的‘成’關鍵字的http異步請求已經發送給了服務器(要經過2s才返回數據給我。),而關鍵字為‘成龍’的http異步請求也發送過去了,它的響應時間是1s就返回數據。那么經過2s之后,得到的將會是關鍵字為‘成’的數據。因為最新的‘成龍’數據(1s)已經被‘成’數據(2s)所覆蓋了。

 

  3)利用axios.CancelToken來終止上一次的異步請求,防止舊關鍵字查詢覆蓋新輸入的關鍵字查詢結果。

import httpService from '@/services/HttpService';
<script>
export default{
	data(){
		return{
			$http: null,
			CancelToken: null,
			cancel: null,
		}
	},
	methods{
		queryDataListByKey() {
			if (this.searchKey.length === 0) {
				this.loadedData = false;
				this.dataList = [];
				return;
			}

			let params = {
				'pageNo': this.pageNo,
				'pageSize': this.pageSize,
				'keyWord': this.searchKey
			};
			this.loading(true);
              // this.cancel === null,意味着第一次請求 if (this.cancel) {
                   // 取消上一次的異步請求 this.cancel('canceled by user'); } this.$http.get('rule/findRuleListByKeyWord', {
                   // 每一次請求關鍵字資源的http異步請求,都要新建一個異步取消操作實例,並賦值給this.cancel cancelToken: new this.CancelToken((c) => { this.cancel = c; }), 'params': params }).then((res) => { this.loading(false); this.loadedData = true; this.processDataList(res); }, (error) => { this.loading(false); this.loadedData = true; this.loadMoreConfig.loading = true; if (error !== null) { this.$vux.toast.show({ text: '數據加載失敗', type: 'text' }); } }); }, } } </script>

 

  4)v-htmlReg為搜索結果的關鍵字高亮顯示

  這一步是在展示數據的組件上做的。

    4.1)HTML結果數據展示部分

<div class="title-info" v-html="ruleTitle"></div>

    4.2)js部分

import httpService from '@/services/HttpService';
<script>
export default{
	props: {
		// 每一條帶關鍵字的結果對象,父組件傳過來的
		item: {},
	},
	computed: {
		ruleTitle() {
		  let titleString = this.item.name;
		  if (!titleString) {
			return '';
		  }
		  if (this.searchValue && this.searchValue.length > 0) {
			// 匹配關鍵字正則
			let replaceReg = new RegExp(this.searchValue, 'g');
			// 高亮替換v-html值
			let replaceString = '<span class="search-text">' + this.searchValue + '</span>';
			// 開始替換
			titleString = titleString.replace(replaceReg, replaceString);
		  }
		  return titleString;
		}
	},
}
</script>

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM