在 Vue3 + ElementPlus 项目中使用 computed 实现前端静态分页

简介: 本文介绍了在Vue3 + ElementPlus项目中使用`computed`属性实现前端静态分页的方法,并提供了详细的示例代码和运行效果。

前言

在Vue项目中,偶尔会遇到一些需求,需要前端实现分页。如果服务端一次性返回所有数据,由前端实现分页,那么这样的分页称为静态分页。本示例使用Vue2写法实现,为的是照顾还没会Vue3写法的童鞋,另外Vue3支持Vue2写法,若想改为Vue3+语法糖等其它写法,自行改改即可。

一、示例代码

(1)/src/views/Example/StaticPager/index.vue

<template>
  <div class="index">
    <div class="index-head">
      <el-form :inline="true" style="display: flex">
        <div class="index-head-left">
          <el-form-item>
            <el-input
              size="small"
              style="width: 200px"
              spellcheck="false"
              clearable
              v-model="tableData.keyWord"
              placeholder="请输入搜索关键字"
              @keyup.enter="handleQueryTableData($event)"
            >
              <template #prefix>
                <el-icon style="cursor: pointer">
                  <Search />
                </el-icon>
              </template>
            </el-input>
          </el-form-item>
        </div>

        <div class="index-head-right">
          <el-form-item>
            <el-button size="small" type="">
              <el-icon :size="14" style="margin-right: 5px"><Download /></el-icon>
              <small>导出 Excel</small>
            </el-button>
          </el-form-item>
        </div>
      </el-form>
    </div>

    <div class="index-body">
      <div class="index-table-container">
        <el-table
          border
          size="small"
          row-key="id"
          ref="tableRef"
          height="100%"
          :data="computedTableData.slice((tableData.pageNumber - 1) * tableData.pageSize, tableData.pageNumber * tableData.pageSize)"
          :row-style="{
            height:'35px'
          }"
          :cell-style="{
            padding:'0px'
          }"
          highlight-current-row
        >
          <el-table-column prop="id" label="ID" width="100" align="center" />
          <el-table-column prop="title" label="名称" width="auto" align="center" show-overflow-tooltip>
            <template #default="scope">
              <p class="table-container-td-title">{
  
  { scope.row.title }}</p>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="80" align="center">
            <template #default="scope">
              <el-tooltip
                effect="dark"
                content="复制"
                placement="top"
                :enterable="false"
                :hide-after="0"
              >
                <el-icon :size="15" style="color: #5e7ce0; margin-right: 10px; cursor: pointer" @click="handleCopyclick(scope.$index, scope.row)">
                  <DocumentCopy />
                </el-icon>
              </el-tooltip>

              <el-tooltip
                effect="dark"
                content="移除"
                placement="top"
                :enterable="false"
                :hide-after="0"
              >
                <el-icon :size="15" style="color: #f56c6c; cursor: pointer" @click="handleDeleteclick(scope.row)">
                  <Delete />
                </el-icon>
              </el-tooltip>
            </template>
          </el-table-column>

          <template #empty v-if="computedTableData.length == 0">
            <div style="font-size: 40px">
              <svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor">
                <path
                  d="M99.096 315.634s-82.58-64.032-82.58-132.13c0-66.064 33.032-165.162 148.646-148.646 83.37 11.91 99.096 165.162 99.096 165.162l-165.162 115.614zM924.906 315.634s82.58-64.032 82.58-132.13c0-66.064-33.032-165.162-148.646-148.646-83.37 11.91-99.096 165.162-99.096 165.162l165.162 115.614z"
                  fill="#6B676E"
                  p-id="1143"
                />
                <path
                  d="M1024 561.548c0 264.526-229.23 429.42-512.002 429.42S0 826.076 0 561.548 283.96 66.064 512.002 66.064 1024 297.022 1024 561.548z"
                  fill="#FFEBD2"
                  p-id="1144"
                />
                <path
                  d="M330.324 842.126c0 82.096 81.34 148.646 181.678 148.646s181.678-66.55 181.678-148.646H330.324z"
                  fill="#E9D7C3"
                  p-id="1145"
                />
                <path
                  d="M644.13 611.098C594.582 528.516 561.55 512 512.002 512c-49.548 0-82.58 16.516-132.13 99.096-42.488 70.814-78.73 211.264-49.548 247.742 66.064 82.58 165.162 33.032 181.678 33.032 16.516 0 115.614 49.548 181.678-33.032 29.18-36.476-7.064-176.93-49.55-247.74z"
                  fill="#FFFFFF"
                  p-id="1146"
                />
                <path
                  d="M611.098 495.484c0-45.608 36.974-82.58 82.58-82.58 49.548 0 198.194 99.098 198.194 165.162s-79.934 144.904-148.646 99.096c-49.548-33.032-132.128-148.646-132.128-181.678zM412.904 495.484c0-45.608-36.974-82.58-82.58-82.58-49.548 0-198.194 99.098-198.194 165.162s79.934 144.904 148.646 99.096c49.548-33.032 132.128-148.646 132.128-181.678z"
                  fill="#6B676E"
                  p-id="1147"
                />
                <path
                  d="M512.002 726.622c-30.06 0-115.614 5.668-115.614 33.032 0 49.638 105.484 85.24 115.614 82.58 10.128 2.66 115.614-32.944 115.614-82.58-0.002-27.366-85.556-33.032-115.614-33.032z"
                  fill="#464655"
                  p-id="1148"
                />
                <path
                  d="M330.324 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z"
                  fill="#464655"
                  p-id="1149"
                />
                <path
                  d="M693.678 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z"
                  fill="#464655"
                  p-id="1150"
                />
              </svg>
              <p style="margin: 0; padding: 0; line-height: 13px; font-size: 13px;">暂无数据 ~</p>
            </div>
          </template>
        </el-table>
      </div>

      <div class="index-pager-container">
        <el-pagination
          small
          background
          layout="total, sizes, prev, pager, next, jumper"
          :current-page="tableData.pageNumber"
          :page-size="tableData.pageSize"
          :page-sizes="[10, 15, 20, 30, 50]"
          :total="computedTableData.length"
          :pager-count="5"
          @current-change="handleCurrentChange"
          @size-change="handleSizeChange"
        >
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      // 表格数据
      tableData: {
    
    
        keyWord: '', // 搜索关键字
        list: [
          {
    
    'id': 1, 'title': '苹果'},
          {
    
    'id': 2, 'title': '香蕉'},
          {
    
    'id': 3, 'title': '葡萄'},
          {
    
    'id': 4, 'title': '雪梨'},
          {
    
    'id': 5, 'title': '橙子'},
          {
    
    'id': 6, 'title': '西瓜'},
          {
    
    'id': 7, 'title': '木瓜'},
          {
    
    'id': 8, 'title': '杨桃'},
          {
    
    'id': 9, 'title': '桃子'},
          {
    
    'id': 10, 'title': '芒果'},
          {
    
    'id': 11, 'title': '榴莲'},
          {
    
    'id': 12, 'title': '山竹'},
        ], // 列表
        selectedList: [], // 已选列表
        pageNumber: 1, // 当前页
        pageSize: 10, // 页码大小
      },
    }
  },
  computed: {
    
    
    /**
     * 计算后的表格数据列表
     */
    computedTableData () {
    
    
      const search = this.tableData.keyWord
      if (search) {
    
    
        return this.tableData.list.filter(item => {
    
    
          console.log('item =>', item)
          return Object.keys(item).some(key => {
    
    
            console.log('key =>', key)
            // return String(item[key]).indexOf(search) > -1
            return String(item.title).indexOf(search) > -1
          })
        })
      } else {
    
    
        return this.tableData.list
      }
    }
  },
  methods: {
    
    
    /**
     * 表格当前页句柄方法
     */
    handleCurrentChange: function(pageNumber) {
    
    
      this.tableData.pageNumber = pageNumber
    },

    /**
     * 表格页码大小句柄方法
     */
    handleSizeChange: function(pageSize) {
    
    
      this.tableData.pageNumber = 1
      this.tableData.pageSize = pageSize
    },

    /**
     * 表格查询句柄方法
     */
    handleQueryTableData() {
    
    
      this.tableData.pageNumber = 1
    },

    /**
     * 复制句柄方法
     */
    handleCopyclick(index, row) {
    
    
      const title = row.title
      const inputElement = document.createElement('input')
      inputElement.value = title
      document.body.appendChild(inputElement)
      inputElement.select()
      document.execCommand('Copy')
      inputElement.remove()

      this.$message({
    
    message: '复制 ' + title + ' 完成', type: 'success', duration: 1000 })
    },

    /**
     * 删除句柄方法
     */
    handleDeleteclick(row) {
    
    
      const index = this.tableData.list.findIndex(
        (item) => item.id === row.id
      )
      if (index != -1) {
    
    
        this.tableData.list.splice(index, 1)
      }
      const title = row.title
      this.$message({
    
    message: '移除 ' + title + ' 完成', type: 'success', duration: 1000 })
    },
  }
}
</script>

<style lang="less" scoped>
  .index {
    
    
    display: flex;
    flex-direction: column;
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: #d9e7ff;

    :deep(.index-head) {
    
    
      display: flex;
      flex-direction: row;
      background-color: #ffffff;
      box-shadow: 0 3px 3px #c0d2f1;

      .el-form {
    
    
        display: flex;
        width: 100%;
        height: 100%;

        .index-head-left {
    
    
          flex: 1;
          padding: 7px 0 0 7px;

          .el-form-item {
    
    
            margin-right: 7px;
            margin-bottom: 7px;

            .el-form-item__content {
    
    
              line-height: unset;

              .el-radio-group {
    
    
                margin-left: 0;
              }
            }
          }
        }

        .index-head-right {
    
    
          padding: 7px 7px 0 0;

          .el-form-item {
    
    
            display: inline-flex;
            margin: 0 0 7px 7px;

            .el-form-item__content {
    
    
              align-items: center;
            }
          }
        }
      }
    }

    :deep(.index-body) {
    
    
      flex: 1;
      display: flex;
      flex-direction: column;
      margin: 7px;
      overflow: hidden;

      .index-table-container {
    
    
        flex: 1;
        position: relative;
        background-color: #ffffff;
        overflow: hidden;

        .el-table {
    
    

          th .cell {
    
    
            color: #000;
            font-weight: normal;
            font-size: 13px;
          }

          td {
    
    
            padding: 2.5px 0;

            .cell {
    
    
              // color: #000;
              font-size: 13px;
              padding: 0 8px;
            }
          }
        }
      }

      .index-pager-container {
    
    
        position: relative;
        width: 100%;
        height: 26px;
        padding: 7px 0;
        background-color: #fff;

        .el-pagination {
    
    
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          margin: 0 auto;
          width: fit-content;

          .btn-prev, .btn-next, .el-pager li {
    
    
            border: 1px solid #dcdfe6;
          }

          .el-pager li.is-active {
    
    
            border-color: #5e7ce0;
          }
        }
      }
    }
  }
</style>

二、运行效果

目录
相关文章
|
10天前
|
前端开发 JavaScript 定位技术
一、前端高德地图注册、项目中引入、渲染标记(Marker)and覆盖物(Circle)
文章介绍了如何在前端项目中注册并使用高德地图API,包括注册高德开放平台账号、引入高德地图到项目、以及如何在地图上渲染标记(Marker)和覆盖物(Circle)。
26 1
|
2月前
|
前端开发 Java 编译器
【前端学java】java基础练习缺少项目?看这篇文章就够了!(完结)
【8月更文挑战第11天】java基础练习缺少项目?看这篇文章就够了!(完结)
34 0
|
2月前
|
JavaScript 前端开发 Java
SpringBoot + Vue 前端后分离项目精进版本
这篇文章详细介绍了一个基于SpringBoot + Vue的前后端分离项目的搭建过程,包括前端Vue项目的初始化、依赖安装、页面创建和路由配置,以及后端SpringBoot项目的依赖添加、配置文件修改、代码实现和跨域问题的解决,最后展示了项目运行效果。
SpringBoot + Vue 前端后分离项目精进版本
|
2月前
|
前端开发 Java C++
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
使用Vite和Vue3构建支持共享组件和分模块独立打包的前端项目的方法。
193 0
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
|
2月前
|
前端开发 Java 编译器
【前端学java】java基础练习缺少项目?看这篇文章就够了!(17)
【8月更文挑战第11天】java基础练习缺少项目?看这篇文章就够了!
28 0
【前端学java】java基础练习缺少项目?看这篇文章就够了!(17)
|
2月前
|
开发者 C# C++
揭秘:如何轻松驾驭Uno Platform,用C#和XAML打造跨平台神器——一步步打造你的高性能WebAssembly应用!
【8月更文挑战第31天】Uno Platform 是一个跨平台应用程序框架,支持使用 C# 和 XAML 创建多平台应用,包括 Web。通过编译为 WebAssembly,Uno Platform 可实现在 Web 上运行高性能、接近原生体验的应用。本文介绍如何构建高效的 WebAssembly 应用:首先确保安装最新版本的 Visual Studio 或 VS Code 并配置 Uno Platform 开发环境;接着创建新的 Uno Platform 项目;然后通过安装工具链并使用 Uno WebAssembly CLI 编译应用;最后添加示例代码并测试应用。
57 0
|
2月前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
76 0
|
2月前
|
前端开发 程序员 API
从后端到前端的无缝切换:一名C#程序员如何借助Blazor技术实现全栈开发的梦想——深入解析Blazor框架下的Web应用构建之旅,附带实战代码示例与项目配置技巧揭露
【8月更文挑战第31天】本文通过详细步骤和代码示例,介绍了如何利用 Blazor 构建全栈 Web 应用。从创建新的 Blazor WebAssembly 项目开始,逐步演示了前后端分离的服务架构设计,包括 REST API 的设置及 Blazor 组件的数据展示。通过整合前后端逻辑,C# 开发者能够在统一环境中实现高效且一致的全栈开发。Blazor 的引入不仅简化了 Web 应用开发流程,还为习惯于后端开发的程序员提供了进入前端世界的桥梁。
57 0
|
2月前
|
前端开发 JavaScript 编译器
【性能革命】Angular Ivy编译器:一场前端开发者的极速盛宴,揭秘应用瘦身与提速的黑科技,让你的Angular项目焕发新生的终极指南
【8月更文挑战第31天】Angular Ivy编译器是Angular团队推出的更新,旨在改善应用性能,减少构建时间和代码量。自Angular 9起,Ivy成为默认编译器。本文通过案例分析,介绍Ivy的工作原理及其优势。以一个复杂应用为例,展示了Ivy如何通过减少生成的JavaScript代码量、优化模板表达式解析等方式提升性能。通过创建示例项目并比较启用与未启用Ivy的构建结果,证明了Ivy在构建速度和文件大小上的显著改进,同时提高了运行时性能。这对于追求高性能和快速开发的应用至关重要。
25 0
|
2月前
|
JavaScript 前端开发 API
解锁前端开发新境界:Vue.js携手Webpack,打造高效构建流程,你的项目值得拥有!
【8月更文挑战第30天】随着前端技术的发展,模块化与组件化趋势愈发显著。Vue.js 以其简洁的 API 和灵活的组件系统,深受开发者喜爱;Webpack 则凭借强大的模块打包能力成为前端工程化的基石。两者结合,不仅简化了组件编写与引用,还通过模块热替换、代码分割等功能大幅提升开发效率。本文将通过具体示例,展示如何利用 Vue.js 和 Webpack 构建高效、有序的前端开发环境。从安装配置到实际应用,逐步解析这一组合的优势所在。
37 0
下一篇
无影云桌面