Element-Plus中表格及分页功能

导入Element-Plus

具体步骤如下:(内容参照官网:安装 | Element Plus

# 选择一个你喜欢的包管理器

# NPM
$ npm install element-plus --save

# Yarn
$ yarn add element-plus

# pnpm
$ pnpm install element-plus

在main.js文件的引入 

// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')

完成以上步骤后即可在官网组件部分查找自己想用的插件进行使用了。 

VUE2版本方式

一、将官网中HTML源码复制到自己的文件中,对其中的参数进行修改。主要修改的是数据的绑定和部分样式的选择。
  <div class="demo-pagination-block">
    <div class="example-demonstration">
      <el-table :data="currentData" style="width: 100%">
        <el-table-column fixed type="index" :index="indexMethod" label="序号" width="50" />
        <el-table-column prop="nativeTip" show-overflow-tooltip label="本国子目" width="100" />
        <el-table-column prop="childrenTip" show-overflow-tooltip label="子目条文" width="100" />
        <el-table-column prop="date" label="数据版本" width="100" />

        <el-table-column fixed="right" label="操作" width="60">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="handleClick(scope.$index)">
              详细
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
<!-- 分页器 -->
    <el-pagination v-model:current-page="searchParams.pagenum" v-model:page-size="searchParams.pagesize" :small="small"
      :disabled="disabled" background layout="total,prev, pager, next, jumper" :total="total"
      @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  </div>

说明:这里我用了首列索引来作为表头元素,但索引值并不是渲染在页面上副本数组中的索引,而是通过该索引计算后的值(即需要渲染在页面上的值),所以通过:index="indexMethod",绑定了indexMethod方法,该方法在methods中定义。

二、将JavaScript中的源码复制后进行修改
	export default {
		data() {
			return {
				searchParams: {
					pagesize: 5, //页面条数
					pagenum: 1, //当前页
				},
				total: 0,
				disabled: false, //是否禁选
				small: true,
				currentData: [], //渲染在页面上的副本
				tableData: [//虚拟数据
						{
						nativeTip: 'Cals',
						childrenTip: 'Tom',
						date: '2016-05-02',

					},
					{
						nativeTip: 'Sdaornia',
						childrenTip: 'Tom',
						date: '2016-05-22',

					},
					{
						nativeTip: 'Csfofif',
						childrenTip: 'Tom',
						date: '2016-05-21',

					}, {
						nativeTip: 'Gsdaw',
						childrenTip: 'Tom',
						date: '2016-05-11',

					}, {
						nativeTip: '2016-05-12',
						childrenTip: 'Tom',
						date: 'California',

					}, {
						nativeTip: 'FedDsa',
						childrenTip: 'Tom',
						date: '2016-05-04',

					},
					{
						nativeTip: 'California',
						childrenTip: 'Tom',
						date: '2016-05-31',

					}, {
						nativeTip: 'California',
						childrenTip: 'Tom',
						date: '2016-05-01',

					}, {
						nativeTip: 'California',
						childrenTip: 'Tom',
						date: '2016-05-04',

					}
				]
			};
		}
		
	}

 说明:这里用的是虚拟数据,所以需要一个副本将虚拟数据的内容进行深拷贝,然后根据当前页面大小和当前页数进行计算,将最终的副本数据进行渲染到页面上。步骤如下:

  1. 每次调用切换页面都将虚拟数据进行深拷贝到副本数据中。
  2. 对副本数据进行处理,根据要渲染第几页数据、一页有几条数据进行裁剪。
  3. 将最终的副本渲染到页面上。
methods: {
		
			// 修改索引
			indexMethod(index) {
				return index + 1 + (this.searchParams.pagenum - 1) * this.searchParams.pagesize
			},

			handleSizeChange(e) {
				console.log('SizeChange', e)

			},
			// 切换当前页面
			handleCurrentChange(e) {
				console.log('CurrentChange', e)

				this.searchParams.pagenum = e

				// 1.将获取到的数据存入副本中 深拷贝
				this.currentData = JSON.parse(JSON.stringify(this.tableData))
				console.log(this.tableData)
				// 2. 对数据进行处理
				let len = this.currentData.length //数据总条数
				console.log(len)
				this.total = len
				console.log('this.total', this.total)
				let num = len - this.searchParams.pagesize //判断是否过长了 多了多少个元素
				console.log(num)
				if (num > 0 && this.searchParams.pagenum === 1) {
					// 2.1 如果是第一页 且长度超过了页面展示长度
					// 进行裁剪 从页面展示的最后一个元素开始 一共num个元素
					this.currentData.splice(this.searchParams.pagesize, num)
					console.log(this.currentData)
				} else if (num > 0 && this.searchParams.pagenum !== 1) {
					// 数据过长 但不是第一页
					// 2.2.1 先裁剪掉前面的元素
					this.currentData.splice(0, (this.searchParams.pagenum - 1) * this.searchParams.pagesize)
					// 2.2.2 再裁剪掉后面的元素
					let len2 = this.currentData.length //判断是否过长了 还多了多少个元素
					if (len2 - this.searchParams.pagesize > 0) {
						this.currentData.splice((this.searchParams.pagesize), len2 - this.searchParams.pagesize)
					}

				}

			}
		},
		onLoad() {
			this.handleCurrentChange(1)
			
		}
项目成果: 

VUE3版本方式

 Vue3和Vue2的区别

两个最本质的区别在于拷贝,因为Vue3使用的是组合式API,所以在响应式基础上,能够对data中的数组进行直接拷贝渲染。

完整项目实例:
<template>

  <div>
    <!-- 面包屑 :separator-icon="ArrowRight"-->
    <el-breadcrumb>
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>账号列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 白色内容区域 -->
    <div class="page_content">
      <div class="flex">
        <div class="input_box">
          <el-input v-model="searchParams.query" placeholder="搜索关键字" class="input-with-select">
            <template #append>
              <el-button @click="searchList"><el-icon>
                  <Search />
                </el-icon></el-button>
            </template>
          </el-input>
        </div>
        <el-button type="primary" @click="addUser">新建用户</el-button>
      </div>
      <!-- 表格 -->
      <!-- 
              el-table  的  data:要展示的数据数组
              el-table-column:列 prop每条数据的对应属性
                label:列标题
                scope.row:相当于一条数据
             -->
      <el-table :data="users" style="width: 100%">
        <el-table-column prop="username" label="姓名" width="180" />
        <el-table-column prop="email" label="邮箱" width="180" />
        <el-table-column prop="mobile" label="电话" />
        <el-table-column prop="role_name" label="角色" />
        <el-table-column prop="mg_state" label="状态">
          <!-- <template #default="scope">
            <el-switch
              v-model="scope.row.mg_state"
              @change="switchChange(scope.row)"
            />
          </template> -->
        </el-table-column>
        <el-table-column label="操作">
          <template #default="scope">
            <el-button type="primary" @click="editRow(scope.row)">编辑</el-button>
            <el-button type="danger" @click="deleteRow(scope.row)">删除</el-button>
          </template>
        </el-table-column>
        <!-- mg_state 状态 -->
      </el-table>
      <!-- 分页 -->
      <el-pagination v-model:currentPage="searchParams.pagenum" v-model:page-size="searchParams.pagesize"
        :page-sizes="[1, 3, 5, 10]" layout="total, sizes, prev, pager, next" :total="total" @size-change="searchList"
        @current-change="searchList" />
    </div>
    
    <!-- 编辑弹窗 -->
    <el-dialog v-model="dialogFormEVisible" title="编辑用户">
      <!-- 
                表单 
                | email    | 邮箱     | 可以为空 |
                | mobile   | 手机号   | 可以为空 |
             -->
      <el-form ref="userForm2" :model="formData2" :rules="rules2">
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="formData2.email" placeholder="请输入用户邮箱" />
        </el-form-item>
        <el-form-item label="手机号" prop="mobile">
          <el-input v-model="formData2.mobile" placeholder="请输入用户手机号" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="flex">
          <el-button>取消</el-button>
          <el-button type="primary" @click="submitEForm(userForm2)">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script>
import { toRefs, reactive, ref } from "vue";
// import { ArrowRight } from "@element-plus/icons-vue";
export default {
  name: "userList",
  setup() {
    const data = reactive({
      searchParams: {
        query: "",
        pagesize: 5,
        pagenum: 1,
      },
      total: 0,
      userList: [
        {
          username: "谭梦寻",
          email: "1232412@qq.com",
          mobile: "123123312312",
          role_name: "管理员",
          mg_state: "正常",
          id: 0,
        },
        {
          username: "江青影",
          email: "123242312@qq.com",
          mobile: "12312331231",
          role_name: "用户",
          mg_state: "正常",
          id: 1,
        },
        {
          username: "诸葛亮",
          email: "1232122@qq.com",
          mobile: "12312331231",
          role_name: "用户",
          mg_state: "正常",
          id: 2,
        },
        {
          username: "刘伯温",
          email: "1231232@qq.com",
          mobile: "12312331231",
          role_name: "用户",
          mg_state: "正常",
          id: 3,
        },
        {
          username: "张角",
          email: "1231232@qq.com",
          mobile: "13344431323",
          role_name: "用户",
          mg_state: "正常",
          id: 4,
        },
        {
          username: "刘备",
          email: "1231232@qq.com",
          mobile: "13344434343",
          role_name: "用户",
          mg_state: "正常",
          id: 5,
        },
        {
          username: "关羽",
          email: "1231232@qq.com",
          mobile: "12542331231",
          role_name: "用户",
          mg_state: "正常",
          id: 6,
        },
        {
          username: "曹操",
          email: "1231232@qq.com",
          mobile: "15678331231",
          role_name: "用户",
          mg_state: "正常",
          id: 7,
        },
      ],
      users: [],
      dialogFormVisible: false,
      dialogFormEVisible: false,
      formData: {
        username: "",
        password: "",
        email: "",
        mobile: "",
      },
      formData2: {
        id: "",
        email: "",
        mobile: "",
      },
      rules: {
        username: [{ required: true, message: "此项为必填", trigger: "blur" }],

        password: [{ required: true, message: "此项为必填", trigger: "blur" }],
        email: [
          {
            required: false,
            pattern:
              /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
            message: "请填写正确邮箱",
            trigger: "blur",
          },
        ],
        mobile: [
          {
            required: false,
            pattern: /^[1][2,3,4,5,6,7,8,9][0-9]{9}$/,
            message: "请填写正确手机号",
            trigger: "blur",
          },
        ],
      },
      rules2: {
        email: [
          {
            required: false,
            pattern:
              /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
            message: "请填写正确邮箱",
            trigger: "blur",
          },
        ],
        mobile: [
          {
            required: false,
            pattern: /^[1][3,4,5,7,8][0-9]{9}$/,
            message: "请填写正确手机号",
            trigger: "blur",
          },
        ],
      },
    });
    const searchList = () => {
      // 使用正则表达式进行模糊查询
      const searchTerm = data.searchParams.query;
      const regex = new RegExp(searchTerm, "gi");
      console.log(data.searchParams);
      data.users = data.userList;
      data.users = data.users.filter((item) => regex.test(item.username));
      let len = data.users.length;
      let num = len - data.searchParams.pagesize;
      // 获取到的数组长度大于页面展示的长度
      if (num > 0 && data.searchParams.pagenum === 1) {
        console.log("展示首页内容!");
        data.users.splice(data.searchParams.pagesize, num);
      } else if (num > 0 && data.searchParams.pagenum !== 1) {
        console.log("展示后面的内容!");
        console.log(
          "前面要删除的数目:" +
          (data.searchParams.pagenum - 1) * data.searchParams.pagesize
        );
        data.users.splice(
          0,
          (data.searchParams.pagenum - 1) * data.searchParams.pagesize
        );
        // 二次截断
        let len2 = data.users.length;
        data.users.splice(
          data.searchParams.pagesize,
          len2 - data.searchParams.pagesize
        );
      }
      data.total = len;
    };
    const addUser = () => {
      data.dialogFormVisible = true;
    };
    // 新增提交
    const submitForm = (formEl) => {
      // validate
      formEl.validate((res) => {
        if (!res) {
          return;
        }
        // 表单通过对象形式新增到数组中
        // data.userList.push(data.formData);
        data.users.push(data.formData);
        // 隐藏弹窗
        data.dialogFormVisible = false;
        // 清空form
        data.formData = {
          username: "",
          password: "",
          email: "",
          mobile: "",
        };
      });
    };
    // 修改提交
    const submitEForm = (formEl) => {
      formEl.validate((res) => {
        if (!res) {
          return;
        }
        // 提交修改
        console.log(data.formData2);
        data.users[data.formData2.id].email = data.formData2.email;
        data.users[data.formData2.id].mobile = data.formData2.mobile;
        data.dialogFormEVisible = false;
        searchList();
      });
    };
    // 状态更改
    const switchChange = (row) => {
      console.log("操作的那条数据", row);
      if (row) {
        searchList();
      }
    };
    // 数据编辑
    const editRow = (row) => {
      console.log("编辑的那条数据", row);
      const { email, mobile, id } = row;
      // 展示编辑表单
      data.dialogFormEVisible = true;
      data.formData2.email = email;
      data.formData2.mobile = mobile;
      data.formData2.id = id;
    };
    // 删除数据
    const deleteRow = (row) => {
      console.log("删除的那条数据", row);
      let i = 0;
      console.log(row.email);
      for (i; i < data.users.length; i++) {
        if (data.users[i].email === row.email) {
          data.users.splice(i, 1);
        }
      }
      console.log(data.users);
    };

    // 方法初始化
    searchList();
    const userForm = ref();
    const userForm2 = ref();
    return {
      ...toRefs(data),
      searchList,
      addUser,
      submitForm,
      submitEForm,
      userForm,
      userForm2,
      // switchChange,
      editRow,
      deleteRow,
    };
  },
};
</script>
<style scoped>
.input_box {
  width: 200px;
  margin-right: 15px;
}
</style>
项目成果图:

总结: 

Element-Plus虽然给我们提供了框架,但是在实际运用时,还需要根据需求来编写代码逻辑,比如我这里用的是虚拟数据,所以需要利用副本来渲染,每一切换页面都要更新副本数据,假如后端直接提供参数来获取对应页数的数据条数,则不需要这样复杂的过程。

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我们来一步步实现基于Vue3、TypeScript和Element Plus的表格分页查询配置。 1. 首先我们需要安装Vue3、Vue Router、Element Plus和Axios等依赖: ```bash npm install vue@next vue-router@4.0.0-beta.8 element-plus@next axios ``` 2. 在`main.ts`引入Vue、VueRouter、Element Plus和Axios: ```typescript import { createApp } from 'vue' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' import axios from 'axios' const app = createApp(App) app.use(router) app.use(ElementPlus) app.config.globalProperties.$axios = axios app.mount('#app') ``` 3. 在`src/components`目录下创建一个`Table.vue`组件,用来展示表格数据: ```html <template> <el-table :data="tableData"> <el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label"></el-table-column> </el-table> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { columns: { type: Array, default: () => [] }, data: { type: Array, default: () => [] } }, computed: { tableData() { return this.data.map(item => { const row = {} this.columns.forEach(column => { row[column.prop] = item[column.prop] }) return row }) } } }) </script> ``` 4. 在`src/components`目录下创建一个`Pagination.vue`组件,用来展示分页控件: ```html <template> <el-pagination :current-page="currentPage" :page-size="pageSize" :total="total" @current-change="handleCurrentChange" @size-change="handleSizeChange" ></el-pagination> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { currentPage: { type: Number, default: 1 }, pageSize: { type: Number, default: 10 }, total: { type: Number, default: 0 } }, methods: { handleCurrentChange(currentPage: number) { this.$emit('update:currentPage', currentPage) }, handleSizeChange(pageSize: number) { this.$emit('update:pageSize', pageSize) } } }) </script> ``` 5. 在`src/views`目录下创建一个`TableDemo.vue`视图组件,用来展示表格分页控件: ```html <template> <div> <el-form :inline="true" :model="query" class="table-demo__form"> <el-form-item v-for="field in fields" :key="field.prop" :label="field.label"> <el-input v-model="query[field.prop]" placeholder="请输入"></el-input> </el-form-item> <el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button> </el-form> <Table :columns="columns" :data="data"></Table> <Pagination :currentPage.sync="currentPage" :pageSize.sync="pageSize" :total="total"></Pagination> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' import axios from 'axios' import Table from '@/components/Table.vue' import Pagination from '@/components/Pagination.vue' export default defineComponent({ components: { Table, Pagination }, setup() { const fields = [ { prop: 'name', label: '姓名' }, { prop: 'age', label: '年龄' }, { prop: 'gender', label: '性别' } ] const columns = [ { prop: 'name', label: '姓名' }, { prop: 'age', label: '年龄' }, { prop: 'gender', label: '性别' } ] const currentPage = ref(1) const pageSize = ref(10) const total = ref(0) const data = ref([]) const query = ref({ name: '', age: '', gender: '' }) const fetchData = async () => { const res = await axios.get('/api/users', { params: { ...query.value, page: currentPage.value, size: pageSize.value } }) data.value = res.data.items total.value = res.data.total } const handleSearch = () => { currentPage.value = 1 fetchData() } fetchData() return { fields, columns, currentPage, pageSize, total, data, query, handleSearch } } }) </script> <style> .table-demo__form { margin-bottom: 20px; } </style> ``` 6. 在`src/router/index.ts`配置路由: ```typescript import { createRouter, createWebHashHistory } from 'vue-router' import TableDemo from '@/views/TableDemo.vue' const routes = [ { path: '/', name: 'TableDemo', component: TableDemo } ] const router = createRouter({ history: createWebHashHistory(), routes }) export default router ``` 7. 在`public`目录下创建一个`api`目录,用来模拟后端接口: ```json // api/users.json { "total": 100, "items": [ { "name": "张三", "age": 18, "gender": "男" }, { "name": "李四", "age": 20, "gender": "女" }, { "name": "王五", "age": 22, "gender": "男" }, { "name": "赵六", "age": 24, "gender": "女" }, { "name": "钱七", "age": 26, "gender": "男" } ] } ``` 8. 在`package.json`添加一个`dev`命令,用来启动开发服务器: ```json { "scripts": { "dev": "vite" } } ``` 9. 启动开发服务器并访问`http://localhost:3000/`,就可以看到我们的表格分页控件了。 以上就是基于Vue3、TypeScript和Element Plus的表格分页查询配置的实现步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值