Vue项目前后端交互大量数据的-之-前端优化方案

1. 数据分页与懒加载

分页请求实现

// 分页请求方法
async fetchPaginatedData(page = 1, pageSize = 20) {
  try {
    this.loading = true;
    const response = await api.get('/large-data', {
      params: { page, pageSize }
    });
    this.data = response.data;
    this.total = response.total;
  } finally {
    this.loading = false;
  }
}

滚动加载更多

<template>
  <div @scroll="handleScroll" class="scroll-container">
    <div v-for="item in loadedData" :key="item.id">
      {{ item.content }}
    </div>
    <div v-if="loadingMore" class="loading-more">加载中...</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      loadedData: [],
      currentPage: 1,
      loadingMore: false,
      hasMore: true
    }
  },
  methods: {
    async handleScroll(event) {
      const { scrollTop, clientHeight, scrollHeight } = event.target
      if (scrollHeight - (scrollTop + clientHeight) < 50 && !this.loadingMore && this.hasMore) {
        this.loadingMore = true
        this.currentPage++
        const newData = await this.fetchMoreData(this.currentPage)
        this.loadedData = [...this.loadedData, ...newData]
        if (newData.length < 20) this.hasMore = false
        this.loadingMore = false
      }
    }
  }
}
</script>

2. 虚拟滚动技术

使用vue-virtual-scroller

<template>
  <RecycleScroller
    class="scroller"
    :items="bigData"
    :item-size="50"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="item">
      {{ item.name }}
    </div>
  </RecycleScroller>
</template>

<script>
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

export default {
  components: { RecycleScroller },
  data() {
    return {
      bigData: [] // 大数据集
    }
  }
}
</script>

<style>
.scroller {
  height: 500px;
}
.item {
  height: 50px;
}
</style>

3. 数据分块处理

// 分块处理大数据
processLargeData(data) {
  const chunkSize = 1000
  for (let i = 0; i < data.length; i += chunkSize) {
    const chunk = data.slice(i, i + chunkSize)
    requestIdleCallback(() => {
      this.renderChunk(chunk)
    })
  }
},

renderChunk(chunk) {
  chunk.forEach(item => {
    // 处理每个数据项
  })
}

4. Web Worker 处理

worker.js

self.onmessage = function(e) {
  const result = e.data.map(item => {
    // 复杂计算处理
    return processedItem
  })
  self.postMessage(result)
}

主线程使用

processDataWithWorker(data) {
  const worker = new Worker('worker.js')
  worker.postMessage(data)
  worker.onmessage = (e) => {
    this.processedData = e.data
    worker.terminate()
  }
}

5. 前端数据缓存

使用IndexedDB缓存

// 初始化IndexedDB
const dbPromise = idb.open('bigDataDB', 1, upgradeDB => {
  upgradeDB.createObjectStore('data', { keyPath: 'id' })
})

// 保存数据
async saveDataToIDB(data) {
  const db = await dbPromise
  const tx = db.transaction('data', 'readwrite')
  const store = tx.objectStore('data')
  await Promise.all(data.map(item => store.put(item)))
  return tx.complete
}

// 读取数据
async getDataFromIDB() {
  const db = await dbPromise
  return db.transaction('data').objectStore('data').getAll()
}

6. 请求优化

请求取消

let cancelToken = null

async fetchData() {
  // 取消之前的请求
  if (cancelToken) {
    cancelToken.cancel('Operation canceled due to new request.')
  }
  
  cancelToken = axios.CancelToken.source()
  
  try {
    const response = await api.get('/data', {
      cancelToken: cancelToken.token
    })
    this.data = response.data
  } catch (error) {
    if (!axios.isCancel(error)) {
      console.error('请求错误:', error)
    }
  }
}

请求合并

// 使用lodash的debounce防抖
import { debounce } from 'lodash'

methods: {
  fetchData: debounce(async function(params) {
    const response = await api.get('/data', { params })
    this.data = response.data
  }, 300)
}

7. 可视化优化

数据采样展示

// 对大数据进行采样
sampleData(data, sampleSize = 1000) {
  if (data.length <= sampleSize) return data
  
  const step = Math.floor(data.length / sampleSize)
  return data.filter((_, index) => index % step === 0)
}

8. 内存管理

大数据释放

// 及时释放不再使用的数据
beforeDestroy() {
  this.bigData = null
  this.processedData = null
  // 强制垃圾回收(非标准方法,仅Chrome支持)
  if (window.gc) window.gc()
}

9. 交互优化

骨架屏加载

<template>
  <div v-if="loading" class="skeleton-container">
    <div v-for="i in 10" :key="i" class="skeleton-item"></div>
  </div>
  <div v-else>
    <!-- 实际内容 -->
  </div>
</template>

<style>
.skeleton-item {
  height: 50px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 400% 100%;
  animation: shimmer 1.5s infinite;
  margin-bottom: 10px;
}

@keyframes shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
</style>

10. 性能监控

性能指标收集

// 使用Performance API监控
measurePerformance() {
  const startTime = performance.now()
  
  // 执行大数据操作
  this.processLargeData()
  
  const endTime = performance.now()
  console.log(`处理耗时: ${endTime - startTime}ms`)
  
  // 内存使用情况(非标准API)
  if (performance.memory) {
    console.log(`内存使用: ${performance.memory.usedJSHeapSize / 1048576}MB`)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

香蕉可乐荷包蛋

努力写有用的code

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

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

打赏作者

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

抵扣说明:

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

余额充值