前言
在公司实习使用vue+element-ui框架进行前端开发,使用表格el-table较为多,有些业务逻辑比较相似,有些地方使用的重复性高,如果多个页面使用相同的功能,就要多次重复写逻辑上差不多的代码,所以打算对表格这个组件进行封装,将相同的代码和逻辑封装在一起,把不同的业务逻辑抽离出来。话不多说,下面就来实现一下吧。
一、原生el-tbale代码——简单の封装
这里直接引用官方的基础使用模板,直接抄过来("htmlcode">
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄' }] } } } </script>
表格の样子
封装后
<template> <el-table :data="tableData" style="width: 100%"> <template v-for="(item, key) in header"> <el-table-column :key="key" :prop="itm.prop " :label="itm.label " :width="itm.width " > </el-table-column> </template> </el-table> </template> <script> export default { data() { return { header: [ { prop: "date", label: "日期", width: "180" }, { prop: "name", label: "姓名", width: "180" }, { prop: "address", label: "地址" } ], tableData: [ { date: "2016-05-02", name: "王小虎", address: "上海市普陀区金沙江路 1518 弄" }, { date: "2016-05-04", name: "王小虎", address: "上海市普陀区金沙江路 1517 弄" }, { date: "2016-05-01", name: "王小虎", address: "上海市普陀区金沙江路 1519 弄" }, { date: "2016-05-03", name: "王小虎", address: "上海市普陀区金沙江路 1516 弄" } ] }; } }; </script>
现在数据还比较少,可能看不出封装组件封装的优势,但是相对于之前代码,这里逻辑上看起来更加清晰,而且修改列的时候直接改动data中的header数据即可,不用再去html代码中去“开刀”( ̄▽ ̄)/。上面是最最最简单的封装了,严格来说只是简单的抽离了一下代码中的数据结构,在正常的业务中肯定不止这么简单的封装,接下来才是重点─━ _ ─━",那就是render函数,关于render可以参考一下这篇博客,使用render函数就可以轻而易举的将这部分逻辑代码抽离出来了。
el-table真正の二次封装
二次封装源代码
<template> <el-table empty-text="暂无数据" ref="table" :data="tableList" border stripe fit highlight-current-row :height="inTableHeight" @selection-change="selectionChange" @row-click="rowClick" > <!-- 选择框 --> <el-table-column v-if="select" type="selection" fixed="left" width="55" align="center" /> <template v-for="(itm, idx) in header"> <!-- 特殊处理列 --> <el-table-column v-if="itm.render" :key="idx" :prop="itm.prop " :label="itm.label " :width="itm.width " :sortable="itm.sortable " :align="itm.align " :fixed="itm.fixed " :show-overflow-tooltip="itm.tooltip" min-width="50" > <template slot-scope="scope"> <ex-slot :render="itm.render" :row="scope.row" :index="scope.$index" :column="itm" /> </template> </el-table-column> <!-- 正常列 --> <el-table-column v-else :key="idx" :prop="itm.prop " :label="itm.label " :width="itm.width " :sortable="itm.sortable " :align="itm.align " :fixed="itm.fixed " :formatter="itm.formatter" :show-overflow-tooltip="itm.tooltip" min-width="50" /> </template> </el-table> </template> <script> // 自定义内容的组件 var exSlot = { functional: true, props: { row: Object, render: Function, index: Number, column: { type: Object, default: null } }, render: (h, context) => { const params = { row: context.props.row, index: context.props.index }; if (context.props.column) params.column = context.props.column; return context.props.render(h, params); } }; export default { components: { exSlot }, props: { tableList: { type: Array, default: () => [] }, header: { type: Array, default: () => [] }, select: { type: Boolean, default: () => false }, height: { type: [Number, String, Function], default: () => null } }, data() { return { inTableHeight: null }; }, created() { //该阶段可以接收父组件的传递参数 this.inTableHeight = this.height; }, mounted() { this.$nextTick(() => { //表格高度自适应浏览器大小 this.changeTableHight(); if (!this.height) { window.onresize = () => { this.changeTableHight(); }; } }); }, destroyed() { //高度自适应事件注销 window.onresize = null; }, watch: { /** * 数据变化后 高度自适应 */ tableList() { this.$nextTick(() => { this.changeTableHight(); }); } }, methods: { /** * 选择框选择后更改,事件分发 */ selectionChange(selection) { this.$emit("selection-change", selection); }, /** * 点击事件 */ rowClick(row, column, event) { this.$emit("row-click", row, column, event); }, /** * 高度自适应 * 当表格展示空间小于460按460px展示,大于的时候高度填充 */ changeTableHight() { if (this.height) { //如果有传进来高度就取消自适应 this.inTableHeight = this.height; this.$refs.table.doLayout(); return; } let tableHeight = window.innerHeight || document.body.clientHeight; //高度设置 let disTop = this.$refs.table.$el; //如果表格上方有元素则减去这些高度适应窗口,66是底下留白部分 tableHeight -= disTop.offsetTop + 66; if (disTop.offsetParent) tableHeight -= disTop.offsetParent.offsetTop; this.inTableHeight = tableHeight < 460 "htmlcode"><template> <div class="hello"> <xd-table :table-list="tableData" :header="header" height="300"></xd-table> </div> </template> <script> export default { name: "HelloWorld", data() { return { header: [ { prop: "w", label: "w" }, { prop: "x", label: "x", formatter: (row) => { return row.x.toFixed(3); }, }, { prop: "d", label: "d", formatter: (row) => { return row.d.toFixed(2); }, }, { label: "操作", render: (h, data) => { return ( <el-button type="primary" onClick={() => { this.handleClick(data.row); }} > 点我获取行数据 </el-button> ); }, }, ], tableData: [ { w: 1, x: 99.25123, d: 0.23892 }, { w: 1, x: 255.6666, d: 0.99134 }, ], }; }, methods: { handleClick(row) { console.log(row); }, }, }; </script>引用组件之前一定要记得先注册,这里我只使用了几个属性,其他属性没有使用,因为是demo,主要还是展示render内嵌代码的方法,还有一个就是官方formatter方法的使用。
有一个需要注意点就是render内我使用了JSX模板语法这里需要在VUE项目中单独去配置一下JSX语法,如果不想使用JSX,直接写也可以,因为不使用JSX语法写出来的内嵌模板代码比较难读所以我就不展示了,个人建议还是使用JSX语法,虽然和原生vue有些地方使用方法不太一样。效果截图
结语
这次封装vue组件,花了我将近半个月的时间,从刚开始的接触到发现bug然后去修改,来来回回终于精简封装出现在这个二次封装的组件,可能对于熟悉vue和element的人来说这个封装其实很简单,但是对于我来说这个算是我这段实习期封装的比较好的一个组件了吧,当然除了封装这个组件还有别的事在做,不可能放着公司的活不干(哈哈哈哈︿( ̄︶ ̄)︿),总之在封装组件过程中学习到了不少东西,也算是一个大大的进步,于是来写一篇博客来记录一下
更新动态
- 孙露《一抹伤HQ》头版限量[WAV+CUE][1G]
- 黄安.1989-一切从头(TP版)【天际唱片】【FLAC分轨】
- 群星.1994-浓情蜜意情歌精丫华纳】【WAV+CUE】
- 邓丽君.1983-淡淡幽情(2022环球MQA-UHQCD限量版)【环球】【WAV+CUE】
- 试音天碟《专业测试第一天碟》经典天碟精选[WAV分轨][1G]
- 试音典范 《情惹发烧情HQCD》人声发烧极品 [WAV+CUE][1G]
- 世界顶级汽车音响试音王《幸福在路上》[低速原抓WAV+CUE][1.1G]
- 老头杯第二届什么时候开始 英雄联盟第二届老头杯开赛时间介绍
- 老头杯第二届什么时候结束 英雄联盟第二届老头杯结束时间介绍
- 老头杯第二届规则是什么 英雄联盟老头杯第二届规则介绍
- 王崴-爵士听堂.蓝色波萨(HQCD)[WAV+CUE]
- 群星《欧美动听情歌·柔情第5季》2CD【DTS-WAV分轨】
- [极品珍藏]德意志进行曲集卡拉扬SACD[WAV+CUE]
- 前暴雪制作人呼吁反击DEI 玩家:夺回文化!
- 腾讯证实子公司Sharkmob大规模裁员:整个市场很低迷