elementPlus的table二次封装

您所在的位置:网站首页 信息时代弊端作文 elementPlus的table二次封装

elementPlus的table二次封装

2024-07-17 01:56:10| 来源: 网络整理| 查看: 265

一、简介

公司业务可能需要进行一些组件的封装,基于第三方elementPlus框架,进行符合UI设计原型的组件封装,这篇主要讲解Table表格的封装,目的主要是梳理封装的思路,下面的代码并不是提供完整的源码,因此不包含样式代码。

二、环境准备

webpack+vue3+elementPlus

官方地址:https://element-plus.gitee.io/zh-CN/component/table.html

三、实现步骤 1,成果示例 2,需求分析 (1)表格组件内包含表格数据展示+分页器+搜索input; (2)表格每列的内容自定义修改,并且支持自定义标签; (3)搜索和分页器都需要和表格数据联动; (4)checkbox勾选状态和分页器联动; (5)搜索栏支持自定义; 3,具体代码 (1)子组件 最终代码示例:       实现思路: 1)table的属性和column的属性要分开;

原因:我们来分析一下上面的代码,首先我们需要用组件封装的思想思考。el-table标签上的属性都可以通过父子传值的方式传进组件。但是el-table-column到底有几个我们不确定,那我们很自然的就会想到组件内部需要用到v-for循环,循环的数据也是通过外部传进来。

所以子组件内部发展为:

                import {defineProps} from 'vue'         defineProps({             tableData:{                 type:Array             },             columnData:{                 type:Array             }         })    

父页面传入的数据发展为:

    const columnData = ref([ { id: 0, prop: "contractName", // width: "140", align: "left", label: "常规名称长字段", }, { id: 1, prop: "contractDate", // width: "200", align: "left", label: "合同日期", }, { id: 2, prop: "contractAmout", // width: "130", align: "right", label: "合同金额", sort: true, formatter: (row) => { return {row.contractAmout}万; }, }, { id: 3, prop: "contractNum", // width: "100", align: "left", label: "合同编号", }, { id: 4, prop: "operation", width: "150", align: "left", label: "操作", type: "slot", formatter: (row,column,cellValue,index) => { //编辑按钮事件 const handleEdit = (val) => { console.log('row',row); console.log('column',column); console.log('cellValue',cellValue); console.log('index',index); // console.log('val',val); alert(val.contractName); }; //删除按钮事件 const handleDelete = (val) => { console.log('row',row); console.log('column',column); console.log('cellValue',cellValue); console.log('index',index); console.log('row',row); // console.log('val',val); alert(val.contractName); }; return ( { handleEdit(row,column,cellValue,index); }} > 编辑 { handleDelete(row,column,cellValue,index); }} > 删除 ); }, }, ]); //表格数据的key键名要和columnData中的prop保持一致 const tableData = ref([ { "id": "1", "contractName": "医院设备1", "contractDate": "2023-01-30 14:44:19", "contractAmout": "50000", "contractNum": "1", }, { "id": "2", "contractName": "医院设备2", "contractDate": "2023-01-29 14:44:19", "contractAmout": "30000", "contractNum": "2", }, { "id": "3", "contractName": "医院设备3", "contractDate": "2023-01-28 15:44:19", "contractAmout": "75000", "contractNum": "3", }, { "id": "4", "contractName": "医院设备4", "contractDate": "2023-01-27 15:44:19", "contractAmout": "80000", "contractNum": "4", }, { "id": "5", "contractName": "医院设备5", "contractDate": "2023-01-26 15:44:19", "contractAmout": "80000", "contractNum": "5", }, { "id": "6", "contractName": "医院设备6", "contractDate": "2023-01-25 15:44:19", "contractAmout": "80000", "contractNum": "6", }, { "id": "7", "contractName": "医院设备7", "contractDate": "2023-01-24 15:44:19", "contractAmout": "80000", "contractNum": "7", }, { "id": "8", "contractName": "医院设备8", "contractDate": "2023-01-23 15:44:19", "contractAmout": "80000", "contractNum": "8", }, { "id": "9", "contractName": "医院设备9", "contractDate": "2023-01-22 15:44:19", "contractAmout": "80000", "contractNum": "9", }, { "id": "10", "contractName": "医院设备10", "contractDate": "2023-01-21 15:44:19", "contractAmout": "80000", "contractNum": "10", } ]);

注意:表格数据的key键名必须和columnData中的prop保持一致;

2)表格的checkbox列和序号列由外部决定是否需要;

也就是外部传入个布尔值去控制是否渲染这两列即可,所以子组件再前面的基础上再加上:

        import {defineProps} from 'vue' defineProps({ tableData:{ type:Array }, columnData:{ type:Array },             selection: Boolean,         index: Boolean, })

如果需要渲染这两列,父页面使用的时候直接传入相应的布尔值即可,如下示例:

    3)插槽支持更多框架内容自定义;

由于formatter的方法内部是react写法,不支持template标签。如果自定义的内容包含el-tag标签或其他可扩展内容时,可以通过插槽实现;

子组件内部就变成了:

                             

父页面使用的时候就可以通过插槽的名称来实现内容的自定义:

tag标签插槽:

{{ row.state }} {{ row.state }} {{ row.state }} {{ row.state }} {{ row.state }}

link扩展链接插槽:

            催填     汇总     重新汇总     重新确认     调整         4)配置搜索表单    

在el-table标签上方加上如上代码,使用插槽支持自定义;

在父页面使用的时候:

      选项一 选项二 重置 确定         import {ref, reactive} from 'vue'     const isShow = ref(false);     const form = reactive({     value1: "张三",     value2: "10",     value3: "",     value4: "",     value5: "",     value6: "",     value7: "",     });    

展开效果图:

隐藏效果图:

5)配置分页器

效果图:

直接运用el-pagination,html代码示例:

        已选择{{ checkNumber }}项 | 取消    

参考elementPlus的方法,结合vue3的写法,js代码示例:

    //checkbox点击事件 const instance = getCurrentInstance(); const table = ref(null); const multipleSelection = ref([]); const checkNumber = ref(null); //取消勾选事件 const toggleSelection = () => { var ultipleTabInstance = toRefs(instance.refs.table); ultipleTabInstance.clearSelection.value(); }; //勾选checkbox事件 const handleSelectionChange = (val) => { console.log("val", val); multipleSelection.value = val; checkNumber.value = multipleSelection.value.length; }; (2)父组件 最终代码示例:     催填 汇总 重新汇总 重新确认 调整 | 二级配置 更多菜单一 更多菜单二 更多菜单三 更多菜单四 上会结束 更多菜单一 更多菜单二 更多菜单三 更多菜单四 二级配置 更多菜单一 更多菜单二 更多菜单三 更多菜单四 上会结束 更多菜单一 更多菜单二 更多菜单三 更多菜单四 二级配置 更多菜单一 更多菜单二 更多菜单三 更多菜单四 {{ row.state }} {{ row.state }} {{ row.state }} {{ row.state }} {{ row.state }} 选项一 选项二 重置 确定 四、真实业务对接

如果业务要求直接传入url就可以实现数据渲染的话,就需要在组件内部去进行数据请求,下面主要进行axios请求mock数据模拟,先测试可行性,再根据真实数据对接即可。

1,实现表格数据成功渲染 (1),步骤一:下载依赖

yarn add mockjs / npm i mockjs

yarn add axios/ npm i axios

(2),步骤二:mock数据模拟

在scr文件夹下新建mock文件夹,新建index.js文件,和mockData文件夹;

在mockData文件里新建table.json文件,写上tableData的数据

{ "totalElements":10, //总条数 "page":1, //当前页码 "rows":5, //每行显示条数 "content":[ { "id": "1", "contractName": "医院设备1", "contractDate": "2023-01-30 14:44:19", "contractAmout": "50000", "contractNum": "1", }, { "id": "2", "contractName": "医院设备2", "contractDate": "2023-01-29 14:44:19", "contractAmout": "30000", "contractNum": "2", }, { "id": "3", "contractName": "医院设备3", "contractDate": "2023-01-28 15:44:19", "contractAmout": "75000", "contractNum": "3", }, { "id": "4", "contractName": "医院设备4", "contractDate": "2023-01-27 15:44:19", "contractAmout": "80000", "contractNum": "4", }, { "id": "5", "contractName": "医院设备5", "contractDate": "2023-01-26 15:44:19", "contractAmout": "80000", "contractNum": "5", }, { "id": "6", "contractName": "医院设备6", "contractDate": "2023-01-25 15:44:19", "contractAmout": "80000", "contractNum": "6", }, { "id": "7", "contractName": "医院设备7", "contractDate": "2023-01-24 15:44:19", "contractAmout": "80000", "contractNum": "7", }, { "id": "8", "contractName": "医院设备8", "contractDate": "2023-01-23 15:44:19", "contractAmout": "80000", "contractNum": "8", }, { "id": "9", "contractName": "医院设备9", "contractDate": "2023-01-22 15:44:19", "contractAmout": "80000", "contractNum": "9", }, { "id": "10", "contractName": "医院设备10", "contractDate": "2023-01-21 15:44:19", "contractAmout": "80000", "contractNum": "10", } ] } ] }

另外在index.js文件中配置mock数据请求地址:

import Mock from 'mockjs'; import tableData from './mockData/tableData.json'; Mock.mock("/getData",(config)=>{ let params = Json.parse(config.body) //这里是请求的参数 return {         success:true,         data:tableData     } })

最后一定要记得在main.js文件中引入mock文件夹下的index.js文件

import './mock/index'

(3),步骤三:封装axios请求,新建api文件夹 import axios from 'axios'; import {ElMessage} from 'element-plus'; //请求表格数据 const getTableData = (url, data)=>{ console.log('post请求参数',data); return axios({ method:'post', url:url, data:data }).then( res => { return res.data }, error => { ElMessage({ type:'error', message:error.message, showClose: true }) } ) } export default getTableData (4),步骤四:组件中引入方法请求数据

组件代码:

import getTableData from "../api/table"; props: { //外部传入url,但也需要给个默认值 url: { type: String, require: true, default: "/getData", }, } //get请求数据方法 const getTableList = (url, options) => { //判断url不存在不继续进行请求 if (!url) { console.log("请求地址不存在!"); return false; } getTableData(url, options).then((res) => { console.log("res", res);     const { data } = res;       //处理请求数据内容渲染表格 tableData.value = data.content; }); }; onMounted(() => { getTableList(props.url, props.requestData); });

使用父页面:

阶段总结:基本上表格的数据已经可以渲染出来了,至于请求request拦截器,需要和后端配合去完善。这里主要是前端先负责渲染出数据和调整效果样式等。

2,实现分页器和搜索框请求参数 (1)步骤一:tableData.json数据中添加分页器参数 "totalElements":10, //总条数 "page":1, //当前页码 "rows":5, //每行显示条数 (2)步骤二:组件内处理请求参数 const total = ref(10); //总条数,可以给个默认值 const pageSize = ref(10); //每页条数,可以给个默认值 const currentPage = ref(1); //当前页码,可以给个默认值 //get请求数据方法 const getTableList = (url, options) => { //判断url不存在不继续进行请求 if (!url) { console.log("请求地址不存在!"); return false; } getTableData(url, options).then((res) => { console.log("res", res); const { data } = res; //处理请求数据内容渲染表格 tableData.value = data.content;      //处理请求数据总条数 ---后端给的 total.value = data.totalElements; //处理请求每页显示条数 ---后端给的 pageSize.value = data.rows; //处理请求当前显示页码 ---后端给的 currentPage.value = data.page; }); }; (3)步骤三:处理页码变化时,传入相应的值给参数进行请求数据

父组件传入请求分页器参数

    const request_data = reactive({     page: 1, //当前页码     rows: 10, //每页显示条数     searchVal: {}, //搜索框输入的值     });     import {     ref,     computed,     onMounted,     getCurrentInstance,     toRefs,     defineExpose,     defineEmits,     } from "vue";         props: {         //分页器请求参数         requestData: {     type: Object,     default: () => ({     page: 1, //当前页数     rows: 10, //显示条数     searchVal: {}, //搜索框的值     }),     },     }     //处理props值可以重新赋值     const emits = defineEmits();        const pageParams = computed({     get: () => {     return props.requestData;     },     set: (val) => {     emits("update:requestData", val);     },     });     //当前页码变化事件 const handleCurrentChange = (val) => {       //把当前页码赋值给请求参数 pageParams.value.page = val;       //请求数据 getTableList(props.url, pageParams.value); }; //每页显示条数变化事件 const sizeChange = (val) => {       //把变化的每页显示条数赋值给请求参数 pageParams.value.rows = val;       //请求数据 getTableList(props.url, pageParams.value) };     //上一页点击事件 const handlePreClick = (val) => { console.log(`handlePreClick,点击了上一页,当前第${val}页`); };     //下一页点击事件 const handleNextClick = (val) => { console.log(`handleNextClick,点击了下一页,当前第${val}页`); };

注意:这里为什么需要用外部传入的requestData?

因为外部使用的时候需要用到searchVal,也就是搜索栏输入框的值;也有可能从刚开始请求表格初始数据的时候,需要传入特定页码和特定关键词的数据,所以暴露在外面可以提高组件的灵活性。

(4)步骤四:验证是否成功传入参数 import Mock from 'mockjs'; import tableData from './mockData/tableData.json'; Mock.mock("/getData",(config)=>{ let params = Json.parse(config.body)   console.log(params) //这里打印验证是否更新参数 return { success:true, data:tableData } }) (5)步骤五:mock手动模拟切换数据的效果

目前分页器和搜索框的值就暴露到了请求数据的参数中。但是在mock中想要实现有切换数据的效果,我们需要根据返回的参数自己模拟mock返回的数据。

import tableData1 from './mockData/tableData1.json' import tableData2 from './mockData/tableData2.json' Mock.mock("/getData",(config)=>{ let params = JSON.parse(config.body) //如果当前页码 = 2,返回第二页数据 if(params.page == 2){ return { success: true, data: tableData1, } }else if(params.page == 1){     //如果当前页码 = 1,返回第一页数据 return { success: true, data: tableData2, }; } })

这样简单的数据切换的效果就实现了,方便去调试传给后端的参数;

3,实现外部调用内部reload方法

因为搜索表单内容是插槽,外部自己写搜索表单的样式和布局,所以包括表单提交事件也是在组件外去操作的,那这个时候就需求去调用内部的请求去重新请求数据。vue3的话可以通过ref来实现。

(1)步骤一:父组件需要给子组件绑定ref     const flexTable = ref(null)        //搜索表单v-model的值     const form = reactive({ value1: "张三", value2: "10", value3: "", value4: "", value5: "", value6: "", value7: "", });         //重置按钮 const resetForm = () => { Object.keys(form).forEach((key) => (form[key] = "")); flexTable.value.reload(form); }; //提交按钮 const onSubmit = () => { flexTable.value.reload(form); }; //输入框enter事件 const handleFilter = (val) => { flexTable.value.reload(val); }; (2)步骤二:子组件处理reload方法     //reload请求方法 const reload = (val) => { pageParams.value.searchVal = val; getTableList(props.url, pageParams.value); }; (3)步骤三:子组件暴露出去reload方法 defineExpose({ reload, }); 五,注意说明 1,关于代码写法

因为之前开发组件的时候需要用到name,所以用的写法是vue3的,没有用到setup语法糖。后面在完善的时候发现可以实现setup语法,也可以保留name。亲测有效。

export default{     name:"组件名" }     //正常业务代码 2,关于组件内其他属性

这里主要讲解了一些重要的常用的属性,至于其他控制样式的属性可以参考elementPlus的组件属性表。

3,关于组件组件开发框架搭建

这个之前也是慢慢研究的,但是还没有整理,整理之后再单独更新吧。

4,关于对接真实接口

上面主要展示的是mock数据的对接模拟,至于真实数据需要对接自己的后端给的字段或者要求等;情况不一。但是大概的思路都可以参考的,大家可以根据自己的真实接口去灵活应用的。

5,关于组件需求

不同业务或许有不同的组件封装需求,以上主要是提供一些需求的一种解决方案,大家可以灵活参考。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭