17_Vue列表過濾_js模糊查詢

2022-10-29 18:02:23

列表過濾

需求分析

  1. 這裡呢有張列表,假設這個列表有一百多條資料
  2. 當我在這個 搜尋方塊當中 搜尋 單個關鍵字的時候 (冬,周,倫),它能把帶了這幾個關鍵字的資訊都給我羅列出來 === 跟資料庫的 模糊查詢類似
  3. 這個需求很常見,請你實現一下

上述這個需求,我們可以使用兩種方式或者更多的方式實現,我們這裡採用計算屬性和監視屬性來寫

前置API的複習

filter

該API內部需要接受一個引數,這個引數型別是函數型別

  • 原生js提供的一個過濾資料的API

  • 參考連結

  • 寫個用法吧

    • const array = [14, 17, 18, 32, 33, 16, 40];
      let newArr = array.filter(function(item){
      	// item 就是該陣列當中的每一項
          // 該API需要提供一個返回值,這個返回值是一個判定條件
          return item > 14
      })
      // 最終結果 newArr = [17,18,32,33,16,40] 將14過濾掉了
      
  • filter並不會改變原有陣列的結構會返回一個新的陣列

indexOf

參考博文

計算屬性實現

使用計算屬性來實現可能要麻煩點,但是我會詳細的把步驟寫下來

知識回顧

  1. 計算屬性是vue當中的一個設定項,computed

  2. computed當中,計算屬性由兩部分組成(key:{} == 屬性名,型別為物件

    • computed:{
      	Calculate:{
      		
      	}
      }
      
  3. 書寫方式兩種,如果不需要對計算屬性進行修改,那麼可以捨棄set設定項的編寫,從而將計算屬性寫為函數形式,函數內部的內容代表的就是get設定項的內容

    1. get設定項

      • 該計算屬性被存取的時候呼叫,所依賴的資料被修改的時候,也會更新
    2. set設定項

      • 當計算屬性整體被修改的時候呼叫,因為計算屬性依賴於其他屬性,所以修改的時候要修改計算屬性所依賴的屬性
    3. computed:{
      	Calculate:{
      		get(){
      		
      		},
      		set(){
      		
      		}
      	}
      }
      

綜上所述,這個功能要被實現,那麼計算屬性必須要出現在頁面當中,並且該計算屬性還需要繫結一個或者多個 依賴屬性

當所依賴的屬性發生修改的時候,計算屬性的get呼叫,而我們的模糊查詢,就在get當中實現

在get當中實現,那麼就可以使用計算屬性的簡寫形式

業務實現

  • 首先我們需要一個input框,在input框中,設定一個v-model雙向繫結(與data當中的資料繫結)
  • filePersons所依賴的資料就是 keyWords
  • keyWords需要參與運算
  • 那剩下的結構就很簡單了,ul與li標籤渲染資料

html

<!-- 建立一個容器 -->
    <div class="app">
        <!-- 模糊查詢 -->
        <input type="text" v-model="keyWords">
        <!-- 列表渲染 -->
        <ul>
            <li v-for="item in filterPersons" :key="item.id">
                {{item.name}} - {{item.age}} - {{item.sex}}
            </li>
        </ul>
    </div>

js

<script>
    const vm = new Vue({
      el: '.app',
      data: {
        name: 'wavesbright',
        keyWords:"",
        // 原始資料
        persons:[
            {id:1,name:'馬冬梅',age:18,sex:"女"},
            {id:2,name:"周冬雨",age:19,sex:"女"},
            {id:3,name:"周杰倫",age:20,sex:"男"},
            {id:4,name:"溫兆倫",age:21,sex:"男"},
        ],
      },
      methods: {
        
      },
      // 計算屬性
      computed:{
          // key:{} == 屬性名,型別為物件
          filterPersons(){
              return this.persons.filter((item) => {
                  return item.name.indexOf(this.keyWords) != -1
              })
          }
      }

    });
</script>

實現效果

注意觀察 右邊資料的變化

關於空串

  • 為什麼,input框中沒有內容的時候,反而資料全部回來了呢?
  • 因為這個時候,input雖然沒有內容,但是它的value值是一個空字串
  • 空字串包含在所有字串當中
  • 判定條件自然為true

監視屬性實現

watch知識點複習

  1. 是vue的一個設定項

  2. 內部採用 鍵值對來設定屬性

    • watch:{
      	keyWords:{
      		// 設定項1
      		// 設定項2
      		// 設定項3
      	}
      }
      
  3. 內部有很多設定項,以handler這個設定項為主

    • handler是一個函數型別

    • 當資料發生改變的時候呼叫該設定項

    • watch:{
      	keyWords:{
      		// 設定項1
      		// 設定項2
      		// 設定項3
      		handler(newValue,oldValue){
                  // 新資料,原始資料
              }
          }
      }
      
  4. watch的寫法有兩種

    1. 一種是在vue當中書寫
    2. 一種是在外部使用vue的 $watch書寫(你明確知道你要監視的屬性是誰
  5. 我們等下使用$watch書寫

準備工作

html

與之前計算屬性一樣,但是這次不需要額外的span標籤了,因為我們只對keyWords進行監視

<!-- 建立一個容器 -->
    <div class="app">
        <!-- 模糊查詢 -->
        <input type="text" v-model="keyWords">
        <!-- 列表渲染 -->
        <ul>
            <li v-for="item in initialArr" :key="item.id">
                {{item.name}} - {{item.age}} - {{item.sex}}
            </li>
        </ul>
    </div>

js

// 我很明確我要監視的屬性是keyWords
    vm.$watch("keyWords",function(newValue){
        // 內部書寫的就是handler函數的內容
        this.initialArr = this.persons.filter((item) => {
            return item.name.indexOf(this.keyWords) != -1
        })
    })

測試

事件分析,屬性解讀

  1. 為什麼我這裡寫了兩個陣列,因為使用了filter進行過濾,而filter會返回一個新陣列
    • 如果data當中只存在一個陣列,原始陣列,那麼當 filter進行過濾的時候,為了同步,我們只能讓原始陣列的值替換為新的filter過濾資料
    • 總之,需要一個原始資料和渲染資料,原始資料無法修改,渲染資料可以修改(迎合filter)
  2. 對persons進行過濾,item為persons陣列當中的每一個物件
    • filter的引數是一個函數型別
    • 該函數需要返回值,返回值是一個判定條件
    • 判定條件我們使用indexOf 的字元匹配,只要匹配成功,那麼indeOf呼叫的返回值就不是-1

filter API自實現

我感覺這個API我用起來不是很順暢

我自己寫一個看看

分析

這是api參考手冊

這是我們剛剛範例當中使用的filter

設計思路

  1. 拋開其他的不談,filter 本質上就是 原型Array上的一個函數 == api

  2. 這個api的結構是這樣的

    • // 這個percolator是一個匿名函數
      function filter(percolator){
          
      }
      
  3. 那麼重點就在這個percolator 身上,它是一個引數,是一個匿名函數

  4. 這個匿名函數有三個引數,對應的就是檔案上的三個引數

    1. currentValue:這是陣列當中的每一項
      • 這個項是怎麼來的 ==> 通過迴圈得到的
    2. index:這是currentValue這個元素,它在陣列當中的索引
    3. arr:currentValue所處的陣列
  5. 把這個搞清楚了,剩下的就很簡單了

開始設計

  1. 首先我們需要在原型物件Array當中,通過prototype 設計一個供 所有陣列型別,呼叫的函數

    • Array.prototype.myFilter = function(percolator){}
      
  2. 既然這個 方法,最終會得到一個新的陣列,不會改變原有陣列結構,那我們肯定要先設計一個新陣列嘛

    • Array.prototype.myFilter = function(percolator){
          // 設計一個新陣列
      	let newArr = [];
      }
      
  3. 我們需要得到 currentValue(迴圈項),這個東西到底如何上手?通過迴圈得到嘛

    1. 通過剛剛在原形物件上設計的 myFilter 函數,我們可以對這個陣列進行基本的迭代

    2. Array.prototype.myFilter = function(percolator){
          // 設計一個新陣列
          let newArr = [];
          // 對當前陣列進行迭代;this的指向是陣列本身
          for(let i =0; i<this.length; i++){
              // this[i] 就代表我們當前的迴圈項,也就是currentValue
          }
      }
      
    3. this[i] 就代表我們當前的迴圈項,也就是currentValue

  4. 那麼現在,值得思考的地方就來了

    1. 我們使用這個for迴圈,是為了得到迴圈項,那麼這個迴圈項給誰呼叫? == 匿名函數percolator
    2. 這個匿名函數,可以接受三個引數,但是currentValue是必須要的,所以這裡我們三個引數都傳進去
    3. 那麼,匿名函數應該用在什麼位置?
      • 我覺得這裡應該寫個判斷,當滿足條件的時候,給newArr新增一個元素
    4. 它需要做什麼事情?
      • 這個判斷,就是匿名函數要做的事情,但是判斷不能寫死,要讓使用者來書寫

完整實現

所以現在結果很明確,我們需要寫個if判斷,當if為true,執行if當中的語句,控制是否為true,交給匿名函數 == percolator 來搞定

  • Array.prototype.myFilter = function(percolator){
        // 設計一個新陣列
        let newArr = [];
        // 對當前陣列進行迭代;this的指向是陣列本身
        for(let i =0; i<this.length; i++){
            // this[i] 就代表我們當前的迴圈項,也就是currentValue
            if(percolator(this[i],i,this)){ // 當前元素,當前索引,對應陣列
               // 滿足條件,給 newArr新增一個元素
               newArr.push(this[i]);
            }
        }
        // 迴圈結束,返回新的陣列
        return newArr;
    }
    

測試

這裡有一個簡單結構的陣列

現在我們呼叫api,myFilter,列印輸出