一步步實(shí)現(xiàn)一個(gè)簡(jiǎn)單的適用于iview的vue表格搜索組件,支持下拉選擇指定列進(jìn)行搜索

最近在使用vue+iview做一個(gè)后臺(tái)管理系統(tǒng),在做表格部分時(shí)發(fā)現(xiàn)iview的表格并不支持搜索,不過(guò)iview易于拓展,可以很方便的拓展出表格搜索功能,比如在iview-admin就存在可搜索表格,但是功能比較基礎(chǔ),而且沒有封裝為單獨(dú)組件,接下來(lái)我們就一步步的實(shí)現(xiàn)一個(gè)支持下拉選擇指定列進(jìn)行搜索的表格搜索組件。完整代碼:https://github.com/shawpo/vue-iview-tableSearch


首先我們可以來(lái)看下iview-admin表格搜索的實(shí)現(xiàn),以示例中按姓名搜索為例,其實(shí)現(xiàn)實(shí)現(xiàn)了按姓名搜索。

// 關(guān)鍵代碼
<template>
......
  <Input 
      v-model="searchConName1" 
      icon="search" 
      @on-change="handleSearch1" 
      placeholder="請(qǐng)輸入姓名搜索..." 
      style="width: 200px" 
  />
......
</template>
<script>
......
export default {
......
    methods: {
        ......
        search (data, argumentObj) {
            let res = data;
            let dataClone = data;
            for (let argu in argumentObj) {
                if (argumentObj[argu].length > 0) {
                    res = dataClone.filter(d => {
                        return d[argu].indexOf(argumentObj[argu]) > -1;
                    });
                    dataClone = res;
                }
            }
            return res;
        },
        handleSearch1 () {
            this.data1 = this.initTable1;
            this.data1 = this.search(this.data1, {name: this.searchConName1});
        },
        ......
    },
    ......
};
</script>
  • 首先簡(jiǎn)單說(shuō)明下這個(gè)示例的實(shí)現(xiàn)流程:將input輸出框的on-change事件與組件的handleSearch1方法綁定,在輸入框內(nèi)容發(fā)生變化時(shí)運(yùn)行handleSearch1 方法。而handleSearch1方法則將表格的初始數(shù)據(jù)數(shù)據(jù)(this.data1)與搜索條件對(duì)象(將搜索列與搜索內(nèi)容拼裝成對(duì)象形式后)傳遞給search方法執(zhí)行搜索,并將表格數(shù)據(jù)設(shè)置search方法返回搜索結(jié)果。
  • 接下來(lái)是代碼的說(shuō)明,從handleSearch1方法開始,其首先將原始的表格數(shù)據(jù)賦值給data1,以保障每次搜索都是從原始表格數(shù)據(jù)中搜索,將搜索列與搜索內(nèi)容拼裝成對(duì)象形式作為搜索條件,將然后將data1以及搜索條件對(duì)象傳遞給search方法,這里的'name'為表格數(shù)據(jù)中對(duì)應(yīng)列內(nèi)容的字段名。接下來(lái)就是重要的search方法了,可以看出這個(gè)方法是支持多條件(多列)搜索的,其首先對(duì)搜索條件對(duì)象進(jìn)行了遍歷,當(dāng)對(duì)象的一個(gè)屬性的值不沒空時(shí)(則說(shuō)明這個(gè)屬性可以作為搜索的一個(gè)條件),通過(guò)函數(shù)filter對(duì)dataClone進(jìn)行過(guò)濾,并將過(guò)濾結(jié)果賦值給dataClone以用于下一個(gè)循環(huán),循環(huán)完畢后,所有的搜索條件都執(zhí)行完畢,dataClone即為搜索結(jié)果,將其返回即可。

接下來(lái)我們就對(duì)這個(gè)簡(jiǎn)單的搜索進(jìn)行拓展以支持下拉選擇指定列進(jìn)行搜索并封裝為單獨(dú)組件,想要支持這一功能,我們首先需要列名以及表格數(shù)據(jù)中對(duì)應(yīng)列內(nèi)容的字段名等信息,而創(chuàng)建iview表格的所需的列配置參數(shù)(columns)中就包含這些信息,因此可以很方便的開發(fā)出適用于iview表格的搜索組件。

<Input
    placeholder="請(qǐng)選擇列名并輸入內(nèi)容..."
    v-model="searchContent"
    @on-change="handleSearch">
    <Select slot="prepend" style="width: 80px" v-model="searchColumn">
        <Option
          v-for="column in searchColumns"
          :value="column.key"
          :key="column.key">
          {{column.title}}
        </Option>
    </Select>
</Input>
  • 完成了UI部分之后就需要為UI提供數(shù)據(jù)完成數(shù)據(jù)綁定,首先是為下拉選擇器提供數(shù)據(jù)
    同樣非常簡(jiǎn)單,父組件使用時(shí)將iview表格的columns參數(shù)對(duì)應(yīng)的對(duì)象數(shù)組(父組件可對(duì)數(shù)組進(jìn)行處理,過(guò)濾不需要支持搜索的列)傳遞過(guò)來(lái)即可。
// 關(guān)鍵代碼
......
<table-search
   ......
   :searchColumns="searchColumns"
   >
</table-search>

......
computed: {
  searchColumns: function () {
    // 過(guò)濾不需要支持搜索的列,這里過(guò)濾掉了“狀態(tài)”列
    return this.menusColumns.filter( (d) => {
      return d['key'] && d['key'] != 'status'
    })
  }
},
......
  • 表格數(shù)據(jù)
    要實(shí)現(xiàn)搜索,當(dāng)然需要表格數(shù)據(jù),與上面iview-admin的示例不同的是,我們將表單搜索封裝成了單獨(dú)組件,因此我們需要從父組件獲取表格數(shù)據(jù),并在完成搜索之后,將父組件的表格數(shù)據(jù)更新為搜索結(jié)果的數(shù)據(jù)。我們可以很容易的想到:使用.sync修飾符從父組件中將表格數(shù)據(jù)傳遞過(guò)來(lái),像上面一樣克隆數(shù)據(jù),執(zhí)行搜索,然后通過(guò)觸發(fā)事件將父組件的表格數(shù)據(jù)更新為搜索結(jié)果的數(shù)據(jù)即可。沒錯(cuò),確實(shí)是這樣的,整個(gè)流程很簡(jiǎn)單,但是這里存在一個(gè)問(wèn)題,父組件的表格數(shù)據(jù)通常是從服務(wù)器中獲取的,存在異步操作。我們需要當(dāng)服務(wù)器端完成異步操作之后再對(duì)其進(jìn)行克隆,否則若克隆的表格數(shù)據(jù)為空,無(wú)論如何搜索得到值都為空。
// 父組件
<table-search
  :tableData.sync="menusData"
  :searchColumns="searchColumns"
  >
</table-search>
watch: {
     // 因父組件表格數(shù)據(jù)通常存在異步操作
     // 需監(jiān)聽props以得到正確的數(shù)據(jù)
     tableData: function (newTableData) {
       if (newTableData.length > 0 && this.tableDataClone.length == 0) {
         this.tableDataClone = newTableData
       }
     }
}
  • 執(zhí)行搜索
    這一過(guò)程與iview-admin的示例非常相似,不同的是要執(zhí)行搜索的列來(lái)自于用戶在下拉選擇中的輸入,因此我們需要獲取用戶輸入并將其處理為搜索條件對(duì)象傳遞給search方法執(zhí)行搜索,而搜索完成后我們需要更新父組件表格數(shù)據(jù)。
 methods: {
      // 表格搜索函數(shù),可支持多列搜索
      search: function (data, argumentObj) {
        let res = data;
        let dataClone = data;
        for (let argu in argumentObj) {
          if (argumentObj[argu].length > 0) {
            res = dataClone.filter(d => {
              return d[argu].indexOf(argumentObj[argu]) > -1;
            });
            dataClone = res;
          }
        }
        return res;
      },
      handleSearch: function () {
        var argumentObjStr = '{"' + this.searchColumn + '": "' + this.searchContent + '"}' // 拼接json
        var argumentObj = JSON.parse(argumentObjStr) // 轉(zhuǎn)為對(duì)象
        var res = this.search(this.tableDataClone, argumentObj) // 執(zhí)行搜索,獲取搜索結(jié)果
        this.$emit('update:tableData', res) // 更新表格數(shù)據(jù)為搜索結(jié)果
      }
},

結(jié)束

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容