vue表格不分页情况下点击查看更多数据

前端表格不分页情况下查看更多数据 – 完整方案

一、问题背景

场景描述

在某些业务中,我们需要显示表格数据,但出于以下原因不使用分页

数据量相对较小(通常 50-500 条)需要用户一次性看到所有数据的概览分页会分散用户注意力报表/统计场景,需要整体展示甲方要求不允许有分页

面临的问题


❌ 如果显示所有数据:页面会非常长,用户需要滚动很久
✅ 解决方案:默认显示部分数据(如 10 条),提供"查看更多"功能

二、5 种常见方案对比

2.1 方案对比表

方案 优点 缺点 适用场景
方案 1 简单易实现 每次点击加载固定数量 流式加载数据
方案 2 一次性加载完 首次加载较慢 数据量不大
方案 3 内存占用少 实现较复杂 数据量特别大
方案 4 用户体验最佳 需要后端支持 专业应用
方案 5 适配多种场景 逻辑相对复杂 大型应用

三、方案 1:基础的”查看更多”(最常用)

3.1 核心思路


初始状态:显示 10 条数据
↓
用户点击"查看更多"
↓
显示 20 条数据
↓
用户点击"查看全部"
↓
显示所有数据
↓
用户点击"收起"
↓
回到初始状态(显示 10 条)

3.2 完整代码


<template>
  <div class="table-container">
    <!-- 表格 -->
    <el-table 
      :data="displayData" 
      stripe 
      border 
     >
      <el-table-column prop="id" label="ID" width="100"></el-table-column>
      <el-table-column prop="name" label="姓名" width="150"></el-table-column>
      <el-table-column prop="email" label="邮箱" width="200"></el-table-column>
      <el-table-column prop="phone" label="电话" width="150"></el-table-column>
      <el-table-column prop="dept" label="部门" width="150"></el-table-column>
      <el-table-column prop="status" label="状态" width="100"></el-table-column>
    </el-table>

    <!-- 控制按钮 -->
    <div class="table-footer">
      <!-- 显示当前数据条数 -->
      <span class="data-count">
        显示 {{ displayData.length }} / {{ allData.length }} 条数据
      </span>

      <!-- 按钮组 -->
      <div class="button-group">
        <!-- 只在数据被隐藏时显示"查看更多"按钮 -->
        <el-button 
          v-if="!showAll && allData.length > defaultRowCount" 
          type="primary" 
          plain 
          size="small"
          @click="showMore">
          查看更多 ({{ allData.length - displayData.length }})
        </el-button>

        <!-- 全部展开时显示"收起"按钮 -->
        <el-button 
          v-if="showAll && allData.length > defaultRowCount" 
          type="info" 
          plain 
          size="small"
          @click="collapse">
          收起
        </el-button>

        <!-- 当接近末尾时显示"回到顶部"按钮 -->
        <el-button 
          v-if="showAll" 
          type="info" 
          plain 
          size="small"
          @click="scrollToTop">
          回到顶部
        </el-button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TableWithViewMore',
  data() {
    return {
      // 所有数据
      allData: [],
      
      // 显示状态
      showAll: false,
      
      // 默认显示行数
      defaultRowCount: 10,
      
      // 当前加载了多少行(用于分步加载)
      currentLoadedCount: 10
    };
  },
  
  computed: {
    // 根据状态决定显示哪些数据
    displayData() {
      if (this.showAll) {
        // 显示全部
        return this.allData;
      } else {
        // 只显示前 N 条
        return this.allData.slice(0, this.defaultRowCount);
      }
    }
  },
  
  mounted() {
    // 模拟获取数据
    this.fetchTableData();
  },
  
  methods: {
    // 获取表格数据
    fetchTableData() {
      // 模拟 API 调用
      const mockData = [];
      for (let i = 1; i <= 100; i++) {
        mockData.push({
          id: i,
          name: `员工${i}`,
          email: `employee${i}@company.com`,
          phone: `138-xxxx-${String(i).padStart(4, '0')}`,
          dept: ['技术部', '销售部', '市场部', '人力资源部'][i % 4],
          status: i % 3 === 0 ? '离职' : '在职'
        });
      }
      this.allData = mockData;
    },
    
    // 查看更多
    showMore() {
      this.showAll = true;
      
      // 平滑滚动到表格顶部
      this.$nextTick(() => {
        const tableElement = this.$el.querySelector('.el-table');
        if (tableElement) {
          tableElement.scrollIntoView({ behavior: 'smooth' });
        }
      });
    },
    
    // 收起
    collapse() {
      this.showAll = false;
      
      // 滚动到表格顶部
      this.$nextTick(() => {
        const tableElement = this.$el.querySelector('.table-container');
        if (tableElement) {
          tableElement.scrollIntoView({ behavior: 'smooth' });
        }
      });
    },
    
    // 回到顶部
    scrollToTop() {
      window.scrollTo({
        top: 0,
        behavior: 'smooth'
      });
    }
  }
};
</script>

<style scoped>
.table-container {
  padding: 20px;
  background: #fff;
  border-radius: 4px;
}

.table-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
}

.data-count {
  color: #606266;
  font-size: 14px;
}

.button-group {
  display: flex;
  gap: 10px;
}
</style>

3.3 核心变量说明

变量 说明 示例

allData
所有数据数组 100 条员工信息

defaultRowCount
默认显示行数 10

showAll
是否显示全部 true/false

displayData
计算属性,根据状态返回数据 前 10 条或全部

四、方案 2:分步加载(渐进式加载)

4.1 核心思路


初始状态:显示 10 条
↓
点击"加载更多"→ 显示 20 条(+10 条)
↓
点击"加载更多"→ 显示 30 条(+10 条)
↓
继续点击直到显示全部

4.2 完整代码


<template>
  <div class="table-container">
    <!-- 表格 -->
    <el-table :data="displayData" stripe border>
      <el-table-column prop="id" label="ID" width="100"></el-table-column>
      <el-table-column prop="name" label="姓名"></el-table-column>
      <el-table-column prop="email" label="邮箱"></el-table-column>
      <el-table-column prop="status" label="状态"></el-table-column>
    </el-table>

    <!-- 加载更多按钮 -->
    <div class="table-footer">
      <span class="data-count">
        已加载 {{ displayData.length }} / {{ allData.length }} 条
      </span>
      
      <!-- 只在还有未加载数据时显示 -->
      <el-button 
        v-if="displayData.length < allData.length" 
        @click="loadMore"
        :loading="isLoading"
        type="primary">
        加载更多 ({{ Math.min(pageSize, allData.length - displayData.length) }} 条)
      </el-button>
      
      <!-- 当全部加载时显示 -->
      <span v-else class="all-loaded">✓ 已加载全部数据</span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'InfiniteLoadTable',
  data() {
    return {
      allData: [],
      displayData: [],
      pageSize: 10,        // 每次加载多少条
      currentPage: 1,
      isLoading: false
    };
  },
  
  mounted() {
    this.fetchTableData();
    this.loadMore();  // 首次加载
  },
  
  methods: {
    fetchTableData() {
      // 获取所有数据
      const mockData = [];
      for (let i = 1; i <= 100; i++) {
        mockData.push({
          id: i,
          name: `员工${i}`,
          email: `employee${i}@company.com`,
          status: i % 3 === 0 ? '离职' : '在职'
        });
      }
      this.allData = mockData;
    },
    
    // 加载更多
    async loadMore() {
      this.isLoading = true;
      
      // 模拟网络延迟
      await new Promise(resolve => setTimeout(resolve, 300));
      
      // 计算要加载的数据
      const startIndex = (this.currentPage - 1) * this.pageSize;
      const endIndex = this.currentPage * this.pageSize;
      
      // 追加新数据到 displayData
      const newData = this.allData.slice(startIndex, endIndex);
      this.displayData = this.displayData.concat(newData);
      
      this.currentPage++;
      this.isLoading = false;
      
      // 可选:平滑滚动到新加载的数据
      this.$nextTick(() => {
        const table = this.$el.querySelector('.el-table');
        if (table) {
          table.scrollIntoView({ behavior: 'smooth', block: 'end' });
        }
      });
    }
  }
};
</script>

<style scoped>
.table-container {
  padding: 20px;
}

.table-footer {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
  margin-top: 20px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
}

.data-count {
  color: #606266;
  font-size: 14px;
}

.all-loaded {
  color: #67c23a;
  font-size: 14px;
  display: flex;
  align-items: center;
}
</style>

五、方案 3:虚拟滚动(大数据量专用)

5.1 核心思路


不管有多少数据(1000+ 条),DOM 中只渲染可见区域的行

用户滚动 ↓ 动态计算可见行 ↓ 更新 DOM ↓ 流畅显示

内存占用:O(n) → O(1),性能提升 10 倍

5.2 使用 vue-virtual-scroller 库


npm install vue-virtual-scroller

<template>
  <div class="virtual-table-container">
    <!-- 虚拟滚动容器 -->
    <virtual-scroller 
      :items="allData" 
      :item-size="40"
      class="virtual-table">
      <template v-slot="{ item, index }">
        <div class="table-row" :key="index">
          <span class="cell">{{ item.id }}</span>
          <span class="cell">{{ item.name }}</span>
          <span class="cell">{{ item.email }}</span>
          <span class="cell">{{ item.status }}</span>
        </div>
      </template>
    </virtual-scroller>
  </div>
</template>

<script>
import VirtualScroller from 'vue-virtual-scroller';

export default {
  name: 'VirtualScrollTable',
  components: {
    VirtualScroller
  },
  data() {
    return {
      allData: []
    };
  },
  mounted() {
    this.generateMockData();
  },
  methods: {
    generateMockData() {
      // 生成 10000 条数据
      const data = [];
      for (let i = 1; i <= 10000; i++) {
        data.push({
          id: i,
          name: `员工${i}`,
          email: `employee${i}@company.com`,
          status: i % 3 === 0 ? '离职' : '在职'
        });
      }
      this.allData = data;
    }
  }
};
</script>

<style scoped>
.virtual-table-container {
  height: 600px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: auto;
}

.virtual-table {
  width: 100%;
}

.table-row {
  display: flex;
  border-bottom: 1px solid #f0f0f0;
  align-items: center;
  min-height: 40px;
  padding: 0 15px;
}

.cell {
  flex: 1;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.table-row:hover {
  background: #f5f7fa;
}
</style>

六、方案 4:服务端分页(推荐用于海量数据)

6.1 核心思路


前端只维护分页参数 (pageNum, pageSize)
每次点击"加载更多"或"下一页"
向服务器请求新的一页数据
追加到列表中显示

6.2 完整代码


<template>
  <div class="server-page-table">
    <!-- 表格 -->
    <el-table 
      :data="displayData" 
      v-loading="loading"
      stripe 
      border>
      <el-table-column prop="id" label="ID"></el-table-column>
      <el-table-column prop="name" label="姓名"></el-table-column>
      <el-table-column prop="email" label="邮箱"></el-table-column>
    </el-table>

    <!-- 分页控制 -->
    <div class="pagination-control">
      <span class="info">
        已加载 {{ displayData.length }} 条,总数 {{ total }}
      </span>
      
      <el-button 
        v-if="displayData.length < total"
        @click="loadNextPage"
        :loading="loading"
        type="primary">
        加载下一页
      </el-button>
      
      <span v-else class="finished">✓ 已加载全部</span>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'ServerPaginationTable',
  data() {
    return {
      displayData: [],    // 已加载的数据
      pageNum: 1,         // 当前页码
      pageSize: 20,       // 每页多少条
      total: 0,           // 总数
      loading: false
    };
  },
  
  mounted() {
    this.loadNextPage();
  },
  
  methods: {
    async loadNextPage() {
      this.loading = true;
      
      try {
        // 调用服务器 API
        const response = await axios.get('/api/table', {
          params: {
            pageNum: this.pageNum,
            pageSize: this.pageSize
          }
        });
        
        // 提取数据
        const { data, total } = response.data;
        
        // 追加到已加载的数据
        this.displayData = this.displayData.concat(data);
        this.total = total;
        
        // 下一页
        this.pageNum++;
        
      } catch (error) {
        this.$message.error('加载失败: ' + error.message);
      } finally {
        this.loading = false;
      }
    }
  }
};
</script>

<style scoped>
.pagination-control {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
  margin-top: 20px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
}

.info {
  color: #606266;
  font-size: 14px;
}

.finished {
  color: #67c23a;
}
</style>

七、方案 5:结合搜索的智能表格

7.1 核心思路


搜索关键词 → 过滤数据 → 显示部分 + 查看更多

搜索时重置分页状态
搜索结果少于阈值时不显示"查看更多"

7.2 完整代码


<template>
  <div class="smart-table">
    <!-- 搜索框 -->
    <div class="search-bar">
      <el-input 
        v-model="searchKeyword"
        placeholder="搜索姓名、邮箱..."
        clearable
        @input="handleSearch">
        <i slot="prefix" class="el-icon-search"></i>
      </el-input>
    </div>

    <!-- 表格 -->
    <el-table 
      :data="displayData" 
      stripe 
      border
     >
      <el-table-column prop="id" label="ID" width="100"></el-table-column>
      <el-table-column prop="name" label="姓名"></el-table-column>
      <el-table-column prop="email" label="邮箱"></el-table-column>
      <el-table-column prop="status" label="状态"></el-table-column>
    </el-table>

    <!-- 搜索结果提示和控制 -->
    <div class="result-footer">
      <span class="result-info">
        搜索结果: 共 {{ filteredData.length }} 条
        <span v-if="searchKeyword">(关键词: "{{ searchKeyword }}")</span>
      </span>

      <div class="controls">
        <!-- 查看更多按钮 -->
        <el-button 
          v-if="!showAll && filteredData.length > defaultRowCount"
          @click="showAll = true"
          type="primary"
          size="small">
          查看全部 ({{ filteredData.length - defaultRowCount }})
        </el-button>

        <!-- 收起按钮 -->
        <el-button 
          v-if="showAll && filteredData.length > defaultRowCount"
          @click="showAll = false"
          type="info"
          size="small">
          收起
        </el-button>

        <!-- 结果为空提示 -->
        <span v-if="filteredData.length === 0" class="no-result">
          没有找到匹配的数据
        </span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'SmartSearchTable',
  data() {
    return {
      allData: [],
      searchKeyword: '',
      showAll: false,
      defaultRowCount: 10
    };
  },
  
  computed: {
    // 根据搜索关键词过滤数据
    filteredData() {
      if (!this.searchKeyword) {
        return this.allData;
      }
      
      const keyword = this.searchKeyword.toLowerCase();
      return this.allData.filter(item =>
        item.name.toLowerCase().includes(keyword) ||
        item.email.toLowerCase().includes(keyword)
      );
    },
    
    // 根据"查看更多"状态决定显示哪些数据
    displayData() {
      if (this.showAll) {
        return this.filteredData;
      } else {
        return this.filteredData.slice(0, this.defaultRowCount);
      }
    }
  },
  
  mounted() {
    this.generateMockData();
  },
  
  methods: {
    generateMockData() {
      const names = ['张三', '李四', '王五', '赵六', '孙七'];
      const data = [];
      for (let i = 1; i <= 50; i++) {
        data.push({
          id: i,
          name: names[i % names.length] + i,
          email: `employee${i}@company.com`,
          status: i % 3 === 0 ? '离职' : '在职'
        });
      }
      this.allData = data;
    },
    
    handleSearch() {
      // 搜索时重置"查看更多"状态
      this.showAll = false;
    }
  }
};
</script>

<style scoped>
.smart-table {
  padding: 20px;
}

.search-bar {
  margin-bottom: 20px;
}

.result-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
}

.result-info {
  color: #606266;
  font-size: 14px;
}

.controls {
  display: flex;
  gap: 10px;
  align-items: center;
}

.no-result {
  color: #909399;
  font-size: 14px;
}
</style>

八、5 个方案的适用场景总结

8.1 选择指南


数据量小于 100 条?
  ↓
  YES → 使用方案 1 或 2(简单高效)
  NO ↓

数据量 100-1000 条且需要快速响应?
  ↓
  YES → 使用方案 2 或 4(渐进式加载)
  NO ↓

数据量超过 1000 条且需要极佳性能?
  ↓
  YES → 使用方案 3(虚拟滚动)
  NO ↓

数据量巨大(10000+ 条)?
  ↓
  YES → 使用方案 4(服务端分页)
  NO ↓

需要同时支持搜索和查看更多?
  ↓
  YES → 使用方案 5(智能表格)

8.2 对比矩阵

指标 方案1 方案2 方案3 方案4 方案5
实现难度 ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
内存占用 ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
适合数据量 <100 100-500 1000+ 10000+ <1000
用户体验 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
性能 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

九、常见问题解决

问题 1:点击”查看更多”后页面无反应


// ❌ 错误:showAll 改了,但 watch 没有
data() {
  return {
    showAll: false,
    tableRef: null
  };
}

// ✅ 正确:添加 watch 监听状态变化
watch: {
  showAll(newVal) {
    this.$nextTick(() => {
      // 在 DOM 更新后平滑滚动
      this.tableRef.scrollIntoView({ behavior: 'smooth' });
    });
  }
}

问题 2:滚动卡顿


// ❌ 原因:使用虚拟滚动但没有设置高度
<virtual-scroller 
  :items="items"
  :item-size="40">
  <!-- 没有设置容器高度 -->
</virtual-scroller>

// ✅ 正确:必须设置容器高度
<div>
  <virtual-scroller :items="items" :item-size="40">
    <!-- ... -->
  </virtual-scroller>
</div>

问题 3:搜索后”查看更多”数字不更新


// ❌ 原因:filteredData 计算时没有考虑 showAll
computed: {
  displayData() {
    // showAll 没有作为依赖项
    return this.filteredData.slice(0, 10);
  }
}

// ✅ 正确:showAll 必须作为依赖项
computed: {
  displayData() {
    if (this.showAll) {
      return this.filteredData;
    }
    return this.filteredData.slice(0, this.defaultRowCount);
  }
}

问题 4:加载更多导致表格重新渲染


// ❌ 原因:每次都重新赋值整个数组
this.displayData = [...this.displayData, ...newData];

// ✅ 正确:直接 push 或 concat
this.displayData = this.displayData.concat(newData);
// 或者
this.displayData.push(...newData);
this.$forceUpdate(); // 必要时强制更新

十、完整的最佳实践模板

10.1 推荐的混合方案(适用大多数场景)


<template>
  <div class="optimal-table">
    <!-- 搜索框 -->
    <div class="search-section">
      <el-input 
        v-model="searchKeyword"
        placeholder="搜索..."
        clearable
        @input="handleSearch">
      </el-input>
    </div>

    <!-- 表格 -->
    <div ref="tableWrapper">
      <el-table 
        :data="displayData"
        v-loading="loading"
        stripe 
        border>
        <el-table-column prop="id" label="ID"></el-table-column>
        <el-table-column prop="name" label="姓名"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
      </el-table>
    </div>

    <!-- 控制区 -->
    <div class="control-bar">
      <span class="stats">
        显示 {{ displayData.length }} / {{ filteredData.length }} 条
        <span v-if="searchKeyword">(搜索结果)</span>
      </span>

      <div class="actions">
        <!-- 查看更多按钮 -->
        <el-button 
          v-if="!showAll && hasMore"
          @click="toggleShowAll"
          type="primary"
          size="small">
          查看更多
        </el-button>

        <!-- 收起按钮 -->
        <el-button 
          v-if="showAll && hasMore"
          @click="toggleShowAll"
          type="info"
          size="small">
          收起
        </el-button>

        <!-- 导出按钮 -->
        <el-button 
          @click="exportToCSV"
          type="success"
          size="small">
          导出
        </el-button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'OptimalTable',
  data() {
    return {
      allData: [],
      searchKeyword: '',
      showAll: false,
      defaultRowCount: 20,
      loading: false
    };
  },
  
  computed: {
    // 搜索过滤
    filteredData() {
      if (!this.searchKeyword) return this.allData;
      
      const kw = this.searchKeyword.toLowerCase();
      return this.allData.filter(item =>
        Object.values(item).some(val =>
          String(val).toLowerCase().includes(kw)
        )
      );
    },
    
    // 显示的数据
    displayData() {
      return this.showAll 
        ? this.filteredData 
        : this.filteredData.slice(0, this.defaultRowCount);
    },
    
    // 是否有更多数据
    hasMore() {
      return this.filteredData.length > this.defaultRowCount;
    }
  },
  
  mounted() {
    this.fetchData();
  },
  
  methods: {
    async fetchData() {
      this.loading = true;
      try {
        // 获取数据
        const data = await this.simulateFetch();
        this.allData = data;
      } finally {
        this.loading = false;
      }
    },
    
    handleSearch() {
      this.showAll = false; // 重置查看更多状态
    },
    
    toggleShowAll() {
      this.showAll = !this.showAll;
      
      // 平滑滚动
      this.$nextTick(() => {
        this.$refs.tableWrapper?.scrollIntoView({ behavior: 'smooth' });
      });
    },
    
    exportToCSV() {
      // 导出逻辑
      const csvContent = this.convertToCSV(this.displayData);
      this.downloadCSV(csvContent);
    },
    
    async simulateFetch() {
      return new Promise(resolve => {
        setTimeout(() => {
          const data = Array(100).fill(0).map((_, i) => ({
            id: i + 1,
            name: `项目${i + 1}`,
            email: `project${i + 1}@example.com`
          }));
          resolve(data);
        }, 500);
      });
    },
    
    convertToCSV(data) {
      const headers = ['ID', '名称', '邮箱'];
      const rows = data.map(item => [item.id, item.name, item.email]);
      return [headers, ...rows]
        .map(row => row.join(','))
        .join('
');
    },
    
    downloadCSV(content) {
      const blob = new Blob([content], { type: 'text/csv' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'data.csv';
      a.click();
      URL.revokeObjectURL(url);
    }
  }
};
</script>

<style scoped>
.optimal-table {
  padding: 20px;
}

.search-section {
  margin-bottom: 20px;
}

.control-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
}

.stats {
  color: #606266;
  font-size: 14px;
}

.actions {
  display: flex;
  gap: 10px;
}
</style>

十一、关键代码速查表

11.1 状态管理


// 基础状态
data() {
  return {
    allData: [],              // 所有原始数据
    showAll: false,           // 是否显示全部
    defaultRowCount: 10,      // 默认行数
    searchKeyword: ''         // 搜索关键词
  };
}

11.2 计算属性


// 过滤数据
computed: {
  filteredData() {
    return this.searchKeyword 
      ? this.allData.filter(...)
      : this.allData;
  },
  
  // 显示数据
  displayData() {
    return this.showAll 
      ? this.filteredData 
      : this.filteredData.slice(0, this.defaultRowCount);
  },
  
  // 是否有隐藏数据
  hasMore() {
    return this.filteredData.length > this.defaultRowCount;
  }
}

11.3 核心方法


// 切换显示更多
toggleShowAll() {
  this.showAll = !this.showAll;
  this.$nextTick(() => {
    // 平滑滚动
    this.$el.querySelector('.table').scrollIntoView({ 
      behavior: 'smooth' 
    });
  });
}

// 处理搜索
handleSearch() {
  this.showAll = false; // 重置查看更多状态
}

十二、总结表

方案 数据量 复杂度 推荐指数
基础”查看更多” <100 ⭐⭐⭐⭐⭐
渐进式加载 100-500 ⭐⭐ ⭐⭐⭐⭐
虚拟滚动 1000+ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
服务端分页 10000+ ⭐⭐⭐ ⭐⭐⭐⭐
智能搜索表格 <1000 ⭐⭐ ⭐⭐⭐⭐

完成!

你现在拥有了 5 种完整的解决方案,从简单到复杂,从小数据量到海量数据。

选择建议

🟢 推荐首选:方案 1(最简单,够用)或方案 5(搜索 + 查看更多结合)🟡 进阶需求:方案 2 或 3🔴 企业级应用:方案 4 结合虚拟滚动

© 版权声明

相关文章

暂无评论

none
暂无评论...