当前位置:   article > 正文

vue3 实现关于 el-table 表格组件的封装以及调用_vue3 el-table

vue3 el-table

一、示例图:

二、组件

  1. <template>
  2. <div class="sn-table" :class="props.colorType === 1 ? '' : 'bg-scroll'">
  3. <el-table :data="tableData" :row-class-name="tableRowClassName" height="500" style="width: 100%;"
  4. :default-sort="[{ prop: '正确率', order: 'descending' },{ prop: '未答题数', order: 'descending' }]"
  5. :class="props.colorType === 1 ? '' : 'bg-scroll'">
  6. <el-table-column align="center" :prop="item.keyName"
  7. :sortable="item.keyName==='正确率'&&props.isExistSelect||item.keyName==='未答题数'&&props.isExistSelect?true:false"
  8. :label="item.keyName" v-for="item in columns"
  9. :width="item.width ? item.width + 'px' : ''">
  10. <template #default="scope">
  11. <div v-if="item.keyName==='正确率'&&props.isExistSelect" class="tag-list">
  12. <el-progress :percentage="scope.row[item.keyName]" color="#00B386" :stroke-width="10" :text-inside="false"/>
  13. </div>
  14. </template>
  15. </el-table-column>
  16. </el-table>
  17. </div>
  18. </template>
  19. <script lang='ts' setup>
  20. type TProps = {
  21. tableData: any[]
  22. columns: any[],
  23. colorType: number, // 颜色类型
  24. isExistSelect: boolean // 是否存在筛选项
  25. }
  26. const props = withDefaults(defineProps<TProps>(), {})
  27. const tableRowClassName = ({ rowIndex }: { rowIndex: number }) => {
  28. if (rowIndex % 2 === 1) {
  29. return props.colorType === 1 ? 'odd-row' : 'class-odd-row'
  30. } else {
  31. return props.colorType === 1 ? 'even-row' : 'class-even-row'
  32. }
  33. }
  34. </script>
  35. <style lang='scss' scoped>
  36. .bg-scroll {
  37. border-radius: 10px;
  38. height: 96%;
  39. overflow-y: scroll;
  40. &::-webkit-scrollbar {
  41. width: 5px;
  42. height: 0 !important;
  43. }
  44. &::-webkit-scrollbar-thumb {
  45. border-radius: 10px;
  46. background: #eeeeee;
  47. }
  48. }
  49. .sn-table {
  50. padding: 0 10px 0 20px;
  51. :deep(.el-table) {
  52. color: #ffffff !important;
  53. tr {
  54. td {
  55. border: none;
  56. padding: 16px 0;
  57. font-size: 15px;
  58. }
  59. }
  60. th.el-table__cell {
  61. background: #141414 !important;
  62. border: none;
  63. color: #00B386;
  64. font-size: 14px;
  65. font-weight: 400;
  66. }
  67. .even-row {
  68. background-color: #333 !important;
  69. }
  70. .odd-row {
  71. background-color: #141414 !important;
  72. }
  73. .class-even-row {
  74. background-color: #333 !important;
  75. }
  76. .class-odd-row {
  77. background-color: #00B386 !important;
  78. }
  79. }
  80. :deep(.el-scrollbar__wrap--hidden-default) {
  81. background: #141414 !important;
  82. }
  83. :deep(.el-table--enable-row-hover) {
  84. .el-table__body {
  85. tr:hover>td.el-table__cell {
  86. color: #8C8C8C;
  87. background: #333 !important;
  88. }
  89. }
  90. }
  91. :deep(.el-table__inner-wrapper) {
  92. &::before {
  93. background-color: transparent;
  94. }
  95. }
  96. :deep(.el-table .ascending .sort-caret.ascending){
  97. border-bottom-color:#00B386 !important;
  98. }
  99. :deep(.el-table .descending .sort-caret.descending){
  100. border-top-color:#00B386 !important;
  101. }
  102. .ok-text{
  103. font-size: 35px;
  104. font-weight: 300;
  105. }
  106. .tag-list{
  107. width: 100%;
  108. padding: 2px 0;
  109. .tag-btn{
  110. border-radius: 5px;
  111. border: 1px solid #EF8714;
  112. color: #EF8714;
  113. padding: 1px 10px;
  114. margin-right: 15px;
  115. &:last-child{
  116. margin-right: 0;
  117. }
  118. }
  119. }
  120. }
  121. :deep(.el-progress){
  122. width: 185px;
  123. margin: 0 auto;
  124. }
  125. :deep(.el-progress__text){
  126. span{
  127. font-size: 16px;
  128. }
  129. }
  130. :deep(.el-progress-bar__outer){
  131. background: #D9D9D9;
  132. }
  133. </style>

三、页面调用

  1. <details-table :tableData="knowInfo" :columns="knowColumns" :isExistSelect="false" :colorType="1"/>
  2. <script setup lang="ts">
  3. import { onMounted, ref } from 'vue'
  4. import CanvasVideo from "@/components/CanvasVideo.vue"
  5. const knowInfo = ref<any[]>([])
  6. const knowColumns = ref<any[]>([])
  7. onMounted(()=>{
  8. init()
  9. })
  10. //数据处理
  11. const init = () => {
  12. const datas = ref([
  13. {studentName:'陈佳颖',correctRate:0,noAnswerCount:13},
  14. {studentName:'丁靖芸',correctRate:0,noAnswerCount:13},
  15. {studentName:'谷雨恒',correctRate:0,noAnswerCount:13},
  16. {studentName:'欧阳江源',correctRate:0,noAnswerCount:13},
  17. {studentName:'任行宽',correctRate:0,noAnswerCount:13},
  18. {studentName:'任彦宇',correctRate:0,noAnswerCount:13},
  19. {studentName:'王骁南',correctRate:0,noAnswerCount:13},
  20. {studentName:'吴骏扬',correctRate:0,noAnswerCount:13}
  21. ])
  22. if (datas && datas.length > 0) {
  23. datas.forEach((it: any, index:number) => {
  24. knowInfo.value.push({
  25. '行号': index+1,
  26. '姓名': it.studentName,
  27. '正确率': it.correctRate,
  28. '未答题数': it.noAnswerCount
  29. })
  30. })
  31. for (const key in knowInfo.value[0]) {
  32. knowColumns.value.push({
  33. keyName: key,
  34. width: key === '行号' ? 140 : null
  35. })
  36. }
  37. }
  38. }
  39. </script>

四、其他

(1)自定义标题

  1. <el-table :data="datas" style="width: 100%;">
  2. <el-table-column label="" prop="name" align="center">
  3. <template #header>
  4. 姓名
  5. </template>
  6. </el-table-column>
  7. </el-table>

(2)自定义下标

  1. <el-table :data="datas" style="width: 100%;">
  2. <el-table-column label="行号" align="center">
  3. <template #default="{$index}">
  4. {{$index+1}}
  5. </template>
  6. </el-table-column>
  7. </el-table>

(3)自定义内容

  1. <el-table :data="datas" style="width: 100%;">
  2. <el-table-column label="姓名" prop="name" align="center">
  3. <template #default="scope">
  4. <div>{{scope.row.name}}s</div>
  5. </template>
  6. </el-table-column>
  7. </el-table>

(4)添加排序(升序、降序)

  1. <el-table :data="datas" style="width: 100%;"
  2. :default-sort="[{ prop: 'rank', order: 'descending' },{ prop: 'time', order: 'descending' }]">
  3. <el-table-column label="排名" prop="rank" sortable align="center"/>
  4. <el-table-column label="时长" prop="time" sortable align="center"/>
  5. </el-table>

(5)多选与单选

1. 单选

  1. <el-table :data="datas" style="width: 100%;"
  2. row-key="id" ref="multipleTable" highlight-current-row @row-click="rowselect" @selection-change="selectGroupChange">
  3. <el-table-column type="selection" width="55" />
  4. <el-table-column label="排名" prop="rank" align="center"/>
  5. <el-table-column label="时长" prop="time" align="center"/>
  6. </el-table>
  7. <script setup lang="ts">
  8. import { ref } from "vue"
  9. const multipleTable = ref()
  10. const handleList = ref([])
  11. // 设置单选||显示高亮
  12. const rowselect = (row:any) => {
  13. multipleTable.value.toggleRowSelection(row)
  14. }
  15. // 选择多个单选框,只取最后选中的那一个
  16. const selectGroupChange = (row:any) => {
  17. if (row.length > 1) {
  18. multipleTable.value.clearSelection()
  19. multipleTable.value.toggleRowSelection(row.pop())
  20. return
  21. }
  22. if (row.length == 1) {
  23. handleList.value = row
  24. } else {
  25. handleList.value = []
  26. }
  27. }
  28. </script>
  29. <style lang='scss' scoped>
  30. // 隐藏表头选择框
  31. :deep(.el-table__header){
  32. .el-checkbox{
  33. display: none;
  34. }
  35. }
  36. </style>

2. 多选

  1. <el-table :data="datas" style="width: 100%;"
  2. row-key="id" @select="handleSelectionChange" @select-all="handleAllChange">
  3. <el-table-column type="selection" width="55" />
  4. <el-table-column label="排名" prop="rank" align="center"/>
  5. <el-table-column label="时长" prop="time" align="center"/>
  6. </el-table>
  7. <script setup lang="ts">
  8. // 选择多个选择框
  9. const handleSelectionChange = (selecteds: any, row: any) => {}
  10. // 全选
  11. const handleAllChange= (row:any) => {}
  12. </script>

五、实例(实现树形数据与懒加载)

示例图:通过点击当前节点,调用接口展示下一节点,实现列表的增删改查

1、添加修改组件 EditForm.vue

  1. <template>
  2. <div>
  3. <el-form
  4. ref="menuEditForm"
  5. :model="form"
  6. :label-width="formLabelWidth"
  7. :size="size"
  8. :rules="rules"
  9. clearable
  10. >
  11. <el-row>
  12. <el-col :span="12">
  13. <el-form-item label="父级字典:" prop="parentId">
  14. <el-cascader ref="myCascader" v-model="form.parentId" :props="{ checkStrictly: true,emitPath:false,expandTrigger:'hover' }" :options="menuTree" :show-all-levels="false" placeholder="请选择父级字典" clearable />
  15. </el-form-item>
  16. </el-col>
  17. <el-col :span="12">
  18. <el-form-item label="字典名称:" :rules="rules.Required" prop="dictionaryName">
  19. <el-input
  20. v-model="form.dictionaryName"
  21. autocomplete="off"
  22. :show-word-limit="true"
  23. placeholder="请输入字典名称"
  24. />
  25. </el-form-item>
  26. </el-col>
  27. </el-row>
  28. <el-row v-if="title==='添加字典'">
  29. <el-col :span="24">
  30. <el-form-item label="字典编码:" :rules="rules.Required" prop="dictionaryCode">
  31. <el-input
  32. v-model="form.dictionaryCode"
  33. autocomplete="off"
  34. :show-word-limit="true"
  35. placeholder="请输入字典编码"
  36. />
  37. </el-form-item>
  38. </el-col>
  39. </el-row>
  40. <el-form-item
  41. label="备注:"
  42. prop="remark"
  43. >
  44. <el-input
  45. v-model="form.remark"
  46. type="textarea"
  47. maxlength="200"
  48. :show-word-limit="true"
  49. autocomplete="off"
  50. />
  51. </el-form-item>
  52. </el-form>
  53. </div>
  54. </template>
  55. <script>
  56. import { getChildrens, getDictionaryInfo, EditDictionary } from '@/api/dictionary'
  57. import rules from '@/utils/rules'
  58. export default {
  59. props: {
  60. id: {
  61. type: Number,
  62. default: 0
  63. },
  64. title: {
  65. type: String,
  66. default: ''
  67. }
  68. },
  69. data() {
  70. return {
  71. menuTree: [], // 字典树
  72. rules: rules,
  73. formLabelWidth: '120px',
  74. size: 'small',
  75. loading: false,
  76. form: {
  77. id: this.id,
  78. parentId: 0,
  79. parentDictionaryName: '',
  80. dictionaryCode: '',
  81. dictionaryName: '',
  82. remark: '',
  83. deleteState: true
  84. }
  85. }
  86. },
  87. created() {
  88. this.fetchInitData()
  89. },
  90. methods: {
  91. handlePagedCallback() {
  92. this.$emit('handlePagedCallback')
  93. },
  94. handleSubmitForm() {
  95. this.$refs['menuEditForm'].validate((valid) => {
  96. if (valid) {
  97. this.loading = true
  98. EditDictionary(this.form).then((res) => {
  99. this.loading = false
  100. if (res.code === 200) {
  101. if (res.data) {
  102. this.$message.success('操作成功')
  103. this.handlePagedCallback()
  104. } else {
  105. this.$message.error('操作失败')
  106. }
  107. } else {
  108. this.$message.error(res.message)
  109. }
  110. })
  111. }
  112. })
  113. },
  114. handleResetForm() {
  115. if (this.$refs['menuEditForm']) {
  116. this.$refs['menuEditForm'].resetFields()
  117. }
  118. },
  119. fetchInitData() {
  120. getChildrens().then((res) => {
  121. if (res.code === 200) {
  122. this.menuTree = JSON.parse(JSON.stringify(res.data).replace(/id/g, 'value').replace(/dictionaryName/g, 'label'))
  123. this.fetchFormData()
  124. }
  125. })
  126. },
  127. fetchFormData() {
  128. this.handleResetForm()
  129. if (this.id !== 0) {
  130. const id = { Id: this.id }
  131. getDictionaryInfo(id).then((res) => {
  132. if (res.code === 200) {
  133. this.form = Object.assign(this.form, res.data)
  134. }
  135. })
  136. }
  137. }
  138. }
  139. }
  140. </script>

2、主页面 index.vue

  1. <template>
  2. <div class="app-container">
  3. <div class="search-container">
  4. <!-- 搜索项目 -->
  5. <el-form :inline="true" :model="search" size="small">
  6. <el-form-item>
  7. <el-input v-model="search.keyword" placeholder="字典名称" />
  8. </el-form-item>
  9. <el-form-item>
  10. <el-button
  11. v-rolebtn="'BTN-ZDGL-查询'"
  12. type="primary"
  13. icon="el-icon-search"
  14. @click="handleReloadPaged"
  15. >查询</el-button>
  16. </el-form-item>
  17. </el-form>
  18. </div>
  19. <div class="toolbar-container">
  20. <!-- 按钮组 -->
  21. <el-button
  22. v-rolebtn="'BTN-ZDGL-新增字典'"
  23. type="success"
  24. size="small"
  25. plain
  26. @click="AddDialog"
  27. >新增</el-button>
  28. <el-button
  29. v-rolebtn="'BTN-ZDGL-编辑字典'"
  30. type="primary"
  31. size="small"
  32. plain
  33. @click="EditDialog"
  34. >修改</el-button>
  35. <el-button
  36. v-rolebtn="'BTN-ZDGL-删除字典'"
  37. type="danger"
  38. size="small"
  39. plain
  40. @click="handleDelete"
  41. >删除</el-button>
  42. </div>
  43. <el-table
  44. ref="myTable"
  45. :data="table.data"
  46. :border="table.border"
  47. style="width: 100%"
  48. empty-text="暂无数据"
  49. row-key="id"
  50. lazy
  51. :load="lazyload"
  52. :default-expand-all="false"
  53. :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  54. @selection-change="handleSelectionChange"
  55. >
  56. <el-table-column type="selection" width="60" />
  57. <el-table-column prop="dictionaryName" label="字典名称" />
  58. <el-table-column prop="dictionaryCode" label="字典编码" />
  59. <el-table-column prop="parentDictionaryName" label="父级字典名称" />
  60. <el-table-column prop="createTime" label="创建时间" />
  61. <el-table-column prop="remark" label="备注" />
  62. </el-table>
  63. <Pagination
  64. :total="pagination.total"
  65. :current="pagination.index"
  66. :page-size="pagination.size"
  67. @handlePaginationChange="handlePaginationChange"
  68. @handleSizeChange="handlePaginationChange"
  69. />
  70. <div class="dialog-container">
  71. <el-dialog
  72. v-if="dialog.edit.visible"
  73. ref="menuEditDialog"
  74. :title="dialog.edit.title"
  75. :visible.sync="dialog.edit.visible"
  76. :width="dialog.edit.width"
  77. :close-on-click-modal="dialog.close"
  78. :close-on-press-escape="dialog.close"
  79. >
  80. <EditForm
  81. :id="dialog.edit.id"
  82. ref="Submit"
  83. :title="dialog.edit.title"
  84. @handlePagedCallback="handleEditCallback"
  85. />
  86. <span slot="footer" class="dialog-footer">
  87. <el-button @click="dialog.edit.visible = false">取 消</el-button>
  88. <el-button type="primary" @click="Submit">确 定</el-button>
  89. </span>
  90. </el-dialog>
  91. </div>
  92. </div>
  93. </template>
  94. <script>
  95. import Pagination from '@/components/Pagination'
  96. import EditForm from './EditForm'
  97. import { getDictionaryNext, getDictionaryRoute, DeleteDictionaryRoute } from '@/api/dictionary'
  98. export default {
  99. components: { Pagination, EditForm },
  100. data() {
  101. return {
  102. search: {
  103. keyword: ''
  104. },
  105. searchId: 0,
  106. // 表格数据
  107. table: {
  108. data: [],
  109. selectRows: [],
  110. border: false
  111. },
  112. currChildren: [],
  113. // 分页数据
  114. pagination: {
  115. index: 1,
  116. size: 20,
  117. total: 0
  118. },
  119. // 弹出层
  120. dialog: {
  121. close: false, // 是否关闭
  122. edit: {
  123. id: 0,
  124. title: '修改字典', // 弹出层title
  125. visible: false, // 弹出层是否显示
  126. width: '800px' // 弹出层宽度
  127. }
  128. },
  129. layzNode: null,
  130. layztreeNode: null,
  131. layzresolve: null
  132. }
  133. },
  134. created() {
  135. this.getDictionaryList()
  136. },
  137. methods: {
  138. lazyload(tree, treeNode, resolve) {
  139. if (tree) {
  140. var data = {
  141. Id: tree.id
  142. }
  143. getDictionaryNext(data).then((res) => {
  144. if (res.code === 200) {
  145. this.layzNode = tree
  146. this.layztreeNode = treeNode
  147. this.layzresolve = resolve
  148. resolve(res.data)
  149. }
  150. })
  151. }
  152. },
  153. Submit() {
  154. this.$refs.Submit.handleSubmitForm()
  155. },
  156. // 勾选
  157. handleSelectionChange(selection) {
  158. this.table.selectRows = selection
  159. },
  160. // 新增
  161. AddDialog() {
  162. this.dialog.edit.id = 0
  163. this.dialog.edit.title = '添加字典'
  164. this.dialog.edit.visible = true
  165. },
  166. // 修改
  167. EditDialog() {
  168. if (this.table.selectRows.length !== 1) {
  169. this.$message.warning('请选择要修改的字典')
  170. } else {
  171. this.dialog.edit.id = this.table.selectRows[0].id
  172. this.dialog.edit.title = '修改字典'
  173. this.dialog.edit.visible = true
  174. }
  175. },
  176. // 修改成功回调
  177. handleEditCallback() {
  178. this.dialog.edit.visible = false
  179. this.dialog.edit.id = 0
  180. this.$nextTick(() => {
  181. this.$set(this.$refs.myTable.store.states.lazyTreeNodeMap, this.layzNode.id, [])
  182. this.lazyload(this.layzNode, this.layztreeNode, this.layzresolve)
  183. this.getDictionaryList()
  184. })
  185. },
  186. // 删除
  187. handleDelete() {
  188. if (this.table.selectRows.length === 0) {
  189. this.$message.warning('未勾选记录')
  190. return
  191. }
  192. const ids = []
  193. this.table.selectRows.forEach((it) => {
  194. ids.push(it.id)
  195. })
  196. this.$confirm('此操作将永久删除勾选记录, 是否继续?').then(() => {
  197. DeleteDictionaryRoute(ids).then((res) => {
  198. if (res.code === 200) {
  199. if (res.data) {
  200. this.$nextTick(() => {
  201. this.getDictionaryList()
  202. this.$set(this.$refs.myTable.store.states.lazyTreeNodeMap, this.layzNode.id, [])
  203. this.lazyload(this.layzNode, this.layztreeNode, this.layzresolve)
  204. })
  205. this.$message.success('操作成功')
  206. } else {
  207. this.$message.error('操作失败')
  208. }
  209. } else {
  210. this.$message.error(res.message)
  211. }
  212. })
  213. })
  214. },
  215. // 列表接口
  216. getDictionaryList() {
  217. var data = {
  218. searchName: this.search.keyword,
  219. searchId: this.searchId,
  220. pageIndex: this.pagination.index,
  221. pageSize: this.pagination.size
  222. }
  223. getDictionaryRoute(data).then((res) => {
  224. if (res.code === 200) {
  225. this.pagination.total = res.data.total
  226. this.table.data = res.data.data
  227. }
  228. })
  229. },
  230. // 重载表格
  231. handleReloadPaged() {
  232. this.pagination.index = 1
  233. this.getDictionaryList()
  234. },
  235. // 分页变更
  236. handlePaginationChange(data) {
  237. this.pagination.index = data.current
  238. this.pagination.size = data.pageSize
  239. this.getDictionaryList()
  240. }
  241. }
  242. }
  243. </script>

       希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/621614
推荐阅读
相关标签
  

闽ICP备14008679号