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 可以实现模糊匹配,精度越高,则实现精准匹配。

猜你喜欢

转载自blog.csdn.net/weixin_47560078/article/details/127682875