vue + flask 做一个全局搜索(左匹配和模糊搜索)

一般来说全局搜索都是由后端负责逻辑的,由于最近想尝试下新的方向,就学着用vue来实现搜索,而后端接口只负责返回所有数据。该功能为在表格里面,搜索符合条件的字段,并重新渲染el-table的 :data=tableData,强行使符合条件的device被渲染出来。重点部门在代码每个method都有注释。
对于搜索框,我采用了el-autocomplete来实现,template的代码如下:

<template>
<div class="handle-box">
                <el-autocomplete
                 v-model="select_word"
                 clearable
                 placeholder="筛选关键词"
                 class="handle-input mr10"
                 :fetch-suggestions="querySearchAsync"
                 :trigger-on-focus="false"></el-autocomplete>
                <el-button type="primary" icon="search" @click="search">搜索</el-button>
                <el-button type="success" @click="reset">重置</el-button>
   </div>
   </template>

script方面的代码如下:

export default {
	data() {
		return  {
			select_word: '',
			searchList: [],
			 timeout:  null,
            search_result: ''
		}
	},
	mounted() {
			this.searchList = this.loadAll()
		},
	methods: {
			// 异步查询
			querySearchAsync(queryString, cb) {
		        var searchList = this.searchList;
		        var results = queryString ? searchList.filter(this.createFilter(queryString)) : searchList;
		        this.search_result = results

		        clearTimeout(this.timeout);
		        this.timeout = setTimeout(() => {
		          cb(results);
		        }, 1);
		      },
		 // el-autocomplete只接受value作绑定,所以后端返回数据的时候用value绑定设备的名字,
		 //后面做全局搜索的时候,不管输入什么,只会出来相应的设备的名字,
		 //但是该设备绑定其他的信息也可以被搜索到
        createFilter(queryString) {
        return (select_word) => {
	          return (select_word.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.param.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.no_device.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.amount.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.unit.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.addr.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ||
	          select_word.supplier.toLowerCase().indexOf(queryString.toLowerCase()) === 0 );
            }
        },
        loadAll() {
        // 直接从后端获取所有数据,return device_list,在mounted阶段让searchList等于这个返回列表
          const url = api.get_hardware_all.url
          let device_list = []
          axios.get(url).then(resp => {
              for(let i = 0; i < resp.data.info_list.length; i += 1) {
                  device_list.push(resp.data.info_list[i])
              }
          })
          return device_list
      },
      //点击搜索的时候,直接在最后让table data等于这个符合条件的table list,这样el-table渲染的时候就直接只显示出符合条件的选项
           search() {
            this.is_search = true;
            let search_table = []
            for (let i = 0; i < this.search_result.length; i += 1) {
            const table_data = {
                no_device: this.search_result[i].no_device,
                name: this.search_result[i].name,
                device: this.search_result[i].value,
                param: this.search_result[i].param,
                amount: this.search_result[i].amount,
                unit: this.search_result[i].unit,
                addr: this.search_result[i].addr,
                supplier: this.search_result[i].supplier
            }
            search_table.push(table_data)
        }
        this.tableData = search_table
        }
		}
}

后端的代码如下:

@hardware_blueprint.route('/get_hardware_all', methods=['GET'])
def get_hardware_all():
    try:
        devices = db.session.query(Device).all()
        info_list = []
        ret = status_code.SUCCESS
        for i in devices:
            info_dict = {
                'no_device': i.no_device,
                'name': i.name,
                'value': i.device,
                'param': i.param,
                'amount': i.amount,
                'unit': i.unit,
                'addr': i.addr,
                'supplier': i.supplier
            }
            info_list.append(info_dict)
        ret.update({'info_list': info_list})
        db.session.close()
        return jsonify(ret)
    except Exception as e:
        print e
        return jsonify(status_code.DEVICE_QUERY_ERROR)

这样做的好处是,当在搜索框输想搜的字段时,会远程搜索联想出符合条件(即所有有该字段的设备的名字)出来,可以进行单个搜素,也可以进行全部模糊搜索出所有设备。
在这里插入图片描述
而在这里如果不点击联想出来的选项进行直接搜索,就可以获得所有有该字段的选项出来。
在这里插入图片描述
模糊搜索

模糊搜索我用el-select组件,后端代码都是一样的,区别就在前端的变化上面:

    <div class="handle-box">
        <el-select
            v-model="select_word"
            filterable
            clearable
            remote
            reserve-keyword
            placeholder="请输入关键词"
            :remote-method="remoteMethod"
            :loading="loading">
            <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
            </el-option>
        </el-select>
        <el-button type="primary" icon="search" @click="search">搜索</el-button>
        <el-button type="success" @click="reset">重置</el-button>
    </div>
    <script>
    export default {
    	data() {
    		return {
    			            searchList: [],
				            search_result: '',
				            options: [],
				            value: [],
				            list: [],
				            loading: false
    		}
    	},
      mounted() {
        this.searchList = this.loadAll()
    },
      methods: {
        reset() {
            this.reload()
        },
      loadAll() {
          const url = api.get_hardware_all.url
          let device_list = []
          axios.get(url).then(resp => {
              for(let i = 0; i < resp.data.info_list.length; i += 1) {
                  device_list.push(resp.data.info_list[i])
              }
          })
          return device_list
      },
    },
        remoteMethod(query) {
        if (query !== '') {
          this.loading = true;
          setTimeout(() => {
            this.loading = false;
            this.options = this.list.filter(item => {
              return item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.amount.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.addr.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.value.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.param.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.supplier.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.unit.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
                item.no_device.toLowerCase().indexOf(query.toLowerCase()) > -1;
            });
          }, 200);
        } else {
          this.options = [];
        }
      },
         search() {
            this.is_search = true;
            let search_table = []
            for (let i = 0; i < this.options.length; i += 1) {
            const table_data = {
                no_device: this.options[i].no_device,
                name: this.options[i].name,
                device: this.options[i].value,
                param: this.options[i].param,
                amount: this.options[i].amount,
                unit: this.options[i].unit,
                addr: this.options[i].addr,
                supplier: this.options[i].supplier
            }
            search_table.push(table_data)
        }
        this.tableData = search_table
        }     
  }
  </script>

核心代码差不多都是一样的,只是组建的使用方法不同而已,所以就不做多讲了。
下图是搜索2600后,下方弹框符合条件的搜索选项
在这里插入图片描述
当点击搜索后(换了一个搜索条件)就把所有符合条件的选项都渲染在列表里面了。在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值