Vue 优化长列表性能与模糊实时搜索实现

一、开源项目地址

vue-virtual-scroller

vue-virtual-scroll-list

二、应用场景

优化长列表或无限列表性能

三、原理

窗口化渲染,只需渲染少数的有效数据,减少创建 DOM 节点和重新渲染组件时间

四、使用示例

参考官方示例

1、创建 Vue 项目

vue create demo

【注】这里用脚手架创建的是vue2.x项目。

2、通过 NPM 安装

npm install vue-virtual-scroll-list --save

3、main.js 引入组件 

import Vue from 'vue'
import App from './App.vue'

import VirtualList from 'vue-virtual-scroll-list'

Vue.component('virtual-list', VirtualList)
Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')

【注】这里需要全局引入滑动窗口组件,否则在 App.vue 没有办法解析组件标签。

4、data.js 模拟生成数据

let idCounter = 0

export function getData(count) {
  const data = []
  for (let index = 0; index < count; index++) {
    data.push({
      id: String(idCounter++),
      text: Math.random()
        .toString(16)
        .substr(10)
    })
  }
  return data
}

data 为对象数组,每个对象包括 id,text 字段属性,text 由随机函数生成。

5、Item 组件

<template>
  <div class="item">
    <div class="id">{{ source.id }} - {{ source.text }}</div>
  </div>
</template>
  
<script>
export default {
  name: 'item-component',
  props: {
    source: {
      type: Object,
      default() {
        return {}
      }
    }
  }
}
</script>
  
<style scoped>
.item {
  display: flex;
  flex-direction: column;
  border-bottom: 1px solid lightgrey;
  padding: 1em;
}
</style>
  

Item 组件用于渲染每一项。

6、App.vue 引用组件

<template>
  <div id="app">
    <div class="wrapper">
      <virtual-list class="list" style="height: 360px; overflow-y: auto;" :data-key="'id'" :data-sources="items"
        :data-component="item" :estimate-size="50" />
    </div>
  </div>
</template>
  
<script>
import Item from './Item'
import { getData } from './data'

export default {
  name: 'App',
  data() {
    return {
      item: Item,
      items: getData(1000)
    }
  }
}
</script>
  
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 1em;
  padding: 1em;
}

.list {
  border: 2px solid steelblue;
  border-radius: 3px;
}
</style>
  

创建一个滑动窗口,渲染一千条数据。

7、测试效果

npm run serve

 渲染一千条数据非常流畅。

五、实时模糊搜索实现

1、实现原理

通过 dataset 与关键字 keywor 进行正则匹配

2、App.vue 代码修改

新增输入框,实时监听输入内容,然后将输入内容作为 keyword 在 dataset 中搜索,若符合正则匹配关系,则将该数据保存在结果集 resultArray,最后返回给滑动窗口渲染。

<template>
  <div id="app">
    <div class="wrapper">

      <!-- 输入框 -->
      <input type="text" placeholder="请输入关键字" v-model="inputVal" @input="initSearchList" value=""
        class="searcher-text" />
      <!-- 动态滑动窗口 -->
      <virtual-list class="list" style="height: 360px; overflow-y: auto;" :data-key="'id'" :data-sources="items"
        :data-component="item" :estimate-size="50" />
    </div>
  </div>
</template>


  
<script>
import Item from './Item'
import { getData } from './data'

export default {
  name: 'App',
  data() {
    return {
      item: Item,
      items: [],
      allDataSet: getData(1000),
      inputVal: ''
    }
  },
  mounted() {
    this.items = this.allDataSet;
  },
  methods: {
    // 捕获输入关键字,动态渲染滑动串口内容
    initSearchList() {
      const keyword = this.inputVal;
      this.items = this.searchKeywordsByRegExp(keyword,this.allDataSet);
    },
    // 从 dataset 中匹配 keyword
    searchKeywordsByRegExp(keyword, dataset) {
      if (!(dataset instanceof Array)) {
        return [];
      }
      var len = dataset.length;
      var resultArray = [];
      var reg = new RegExp(keyword);
      for (var i = 0; i < len; i++) {
        // 如果字符串中不包含目标字符会返回-1
        if (dataset[i]['text'].match(reg)) {
          resultArray.push(dataset[i]);
        }
      }
      return resultArray;
    }
  },
}
</script>
  
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 1em;
  padding: 1em;
}

.list {
  border: 2px solid steelblue;
  border-radius: 3px;
}

.searcher-text {
  width: 99%;
  height: 28px;
  margin-bottom: 10px;
  border: 2px solid steelblue;
  border-radius: 3px;
}
</style>
  

3、效果测试

 

可以看到,在 1000 条数据里匹配 ab 可以实现模糊匹配,精度越高,则实现精准匹配。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,这是一个比较常见的场景,我可以给你提供一个简单的示例代码。假设我们要从后台获取一组数据,并且要对其中的某个字段进行模糊搜索,可以按照以下步骤进行实现: 1. 在 Vue 组件中定义一个搜索框和一个数据列表,代码如下: ```html <template> <div> <input type="text" v-model="searchText" @input="search" /> <ul> <li v-for="item in dataList" :key="item.id">{{ item.name }}</li> </ul> </div> </template> <script> export default { data() { return { dataList: [], // 存放从后台获取到的数据 searchText: "", // 存放搜索框中的文本 }; }, methods: { search() { // 实现搜索功能的方法 }, }, }; </script> ``` 2. 在 `mounted` 钩子中获取数据,代码如下: ```javascript export default { data() { return { dataList: [], // 存放从后台获取到的数据 searchText: "", // 存放搜索框中的文本 }; }, mounted() { // 发起请求,获取数据 axios.get("/api/dataList").then((res) => { this.dataList = res.data; }); }, methods: { search() { // 实现搜索功能的方法 }, }, }; ``` 3. 实现搜索功能的方法。我们可以通过过滤器的方式来实现模糊搜索。代码如下: ```javascript export default { data() { return { dataList: [], // 存放从后台获取到的数据 searchText: "", // 存放搜索框中的文本 }; }, mounted() { // 发起请求,获取数据 axios.get("/api/dataList").then((res) => { this.dataList = res.data; }); }, methods: { search() { // 过滤数据 this.dataList = this.dataList.filter((item) => item.name.includes(this.searchText) ); }, }, }; ``` 这样,当用户在搜索框中输入文本时,就会触发 `search` 方法,对数据进行过滤,从而实现模糊搜索功能。需要注意的是,这只是一个简单的示例,实际项目中还需要考虑一些细节问题,比如如何处理请求失败、如何优化搜索性能等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余衫马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值