当前位置:   article > 正文

vue3封装element-plus的el-table_vue3+elementplus table封装

vue3+elementplus table封装

封装的el-table公共组件table.vue
注意深拷贝用的lodash方法,以及使用了jsx插件渲染列的标签和事件
在这里插入图片描述

父组件far.vue

<template>
  <JgTable :tableDataObj="tableData" @update:editItem="updateEditItem"
    @update:handleSelectionChange="updateHandleSelectionChange" @update:changeRadio="updateChangeRadio"
    @update:sortChange="updateSortChange"></JgTable>
</template>
<script lang="jsx">
import { ref, defineComponent, toRefs, reactive, onMounted, getCurrentInstance } from 'vue'
import { Delete, Edit, Download, QuestionFilled, EditPen, Tickets } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'


export default {
  name: "EquipmentDefect",
  setup() {
    let tableData = ref({
      tableLoading: false,
      // title:名称 field:key type:单选复选框 width minWidth maxWidth showOverflowTooltip formatter:格式化内容
      columnsData: [
        { title: '多选', type: 'selection', width: 55 },
        { title: '单选', type: 'radio', width: 55 },
        { title: '缺陷名称', field: 'aa', formType: 'input', width: 120 },
        { title: '缺陷描述', field: 'bb', formType: 'input', showOverflowTooltip: true },
        { title: '缺陷发布时间', field: 'cc', formType: 'date', dateType: 'YYYY-MM-DD', width: 140 },
        // { title: '缺陷发布时间',  field: 'cc', formType: 'datetime', dateType: 'YYYY-MM-DD HH:mm:ss' },
        {
          title: '设备类型', field: 'dd', formType: 'select', width: 120, selectList: [
            { name: '横向隔离', value: 0 },
            { name: '纵向加密', value: 1 },
            { name: '防火墙', value: 2 },
            { name: '监测装置', value: 3 },
            { name: '运维网关', value: 4 },
            { name: '其他', value: 5 },
          ],

          formatter: (row) => {
            const val = [
              { name: '横向隔离', value: 0 },
              { name: '纵向加密', value: 1 },
              { name: '防火墙', value: 2 },
              { name: '监测装置', value: 3 },
              { name: '运维网关', value: 4 },
              { name: '其他', value: 5 },
            ].find(item => item.value === row.dd)?.name || ''
            return <span>{val}</span>
          }
        },
        { title: '设备厂家', field: 'ee', formType: 'input' },
        { title: '设备版本', field: 'ff', formType: 'input', width: 160, showOverflowTooltip: true },
        {
          title: '缺陷设备数量', field: 'gg', formType: 'input', sortable: 'custom',
          formatter: (row, column) => {
            // console.log(112,row, column); // 直接{row}{column} 不会显示内容
            return [<span onClick={() => clickItem(row, 'view')}> {row.gg} </span>]
          }
        },
        {
          title: '缺陷反馈状态', field: 'hh', formType: 'radio', minWidth: 100, selectList: [
            { name: '已反馈', value: 1 },
            { name: '未反馈', value: 0 },
          ],
          formatter: (row) => (
            row ? <el-tag style="border: none;" class="cursor" type={row.hh === 1 ? 'green' : 'warning'}>{row.hh === 1 ? '已反馈' : row.hh === 0 ? '未反馈' : ''}</el-tag> : ''
          )
        },
        {
          title: '缺陷处置进度', field: 'ii', formType: 'progress',
          formatter: (row) => (
            <el-progress class="table_progress" width="13" stroke-width="2" type="circle" percentage={row.ii} />
          )
        },
        // {
        //   title: '测试', field: 'ceshi',width: 200,
        //   formatter: (row, column) => {
        //     // console.log(112,row, column); // 直接{row}{column} 不会显示内容
        //     return  [<el-tag type={row.ceshi == "可发放" ? "success" : "danger"} onClick={() => editItem(row, 'view')}> {row.ceshi} </el-tag>, <span>{column.label}</span>]
        //   }
        // },
        {
          title: '操作', field: 'caozuo', width: 220,
          formatter: (row) => (
            [
              <el-button link type="primary" size="small" icon={Tickets} onClick={() => editItem(row, 'view')} >查看</el-button >,
              <el-button link type="primary" size="small" icon={EditPen} onClick={() => editItem(row, 'edit')} >编辑</el-button >,
              <el-button link type="primary" size="small" icon={Delete} onClick={() => editItem(row, 'delete')} >删除</el-button >,
            ]
          )
        },

      ],
      data: Array.from({ length: 7 }).map((ele, index) => {
        return {
          aa: '客户端不适配',
          bb: '客户端无法适配凝思 4.2.40',
          cc: '2023-7-20',
          dd: Math.floor(Math.random() * 5),
          ee: '帕拉迪',
          ff: 'PLD Sys 61012100',
          gg: Math.floor(Math.random() * 20),
          hh: Math.floor(Math.random() * 2),
          ii: Math.floor(Math.random() * 101),
          ceshi: 123,
        }
      })
    })

    const clickItem = (row, type) => {
      console.log(row, type);
      ElMessage({
        type: 'success',
        message: '点击',
      })
    }
    // 编辑或查看
    const editItem = (row, type) => {
      switch (type) {
        case 'view':
        case 'edit':
          console.log(row, type);
          break;
        case 'delete':
          deleteItem(row, type)
          break;

        default:
          break;
      }
    }

    // 删除
    const deleteItem = (row, type) => {
      ElMessageBox.confirm(
        '确定删除该列?',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        }
      )
        .then(() => {
          ElMessage({
            type: 'success',
            message: 'Delete completed',
          })
        })
        .catch(() => {
        })
    }

    // 子组件调用父组件的测试事件
    const updateEditItem = (data) => {
      console.log('子组件调用父组件的测试事件', data);
      editItem(data.row, data.type)
    }
    const updateHandleSelectionChange = (data) => {
      console.log('updateHandleSelectionChange', data);
    }
    const updateChangeRadio = (data) => {
      console.log('updateChangeRadio', data);
    }
    const updateSortChange = (data) => {
      console.log(data);
    }
    onMounted(() => {

    })
    // 将变量和函数返回,以便在模版中使用
    return {
      tableData,

      ElMessageBox,

      clickItem, // 点击
      editItem, // 查看编辑
      deleteItem, // 删除

      // 子传父表格事件
      updateEditItem,
      updateHandleSelectionChange,
      updateChangeRadio,
      updateSortChange,

      // icon
      Edit,
      Download,
      QuestionFilled,
      EditPen,
      Tickets,
      Delete,

    };
  },
};
</script>
<style lang="scss" scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195

封装的table.vue


<template>
  <div class="page-view flex-center">
    <el-table v-loading="tableData.tableLoading" ref="multipleTableRef" class="jg-table" :data="tableData.data"
      style="width: 100%;" @selection-change="handleSelectionChange" @row-click="rowClick" @sort-change="sortChange">

      <template v-for="(item, index) in  tableData.columnsData " :key="index">

        <!-- 多选 -->
        <el-table-column v-if="item.type === 'selection'" :type="item.type" :width="item.width" />
        <!-- 单选 -->
        <el-table-column v-else-if="item.type === 'radio'" :width="item.width" class-name="no-radio-label">
          <template #default="{ row, $index }">
            <el-radio @change="changeRadio" v-model="radioIndex" :label="row"></el-radio>
          </template>
        </el-table-column>
        <!-- 渲染formatter -->
        <el-table-column v-else :property="item.field" :label="item.title" :width="item.width" :min-width="item.minWidth"
          :max-idth="item.maxWidth" :showOverflowTooltip="item.showOverflowTooltip" :sortable="item.sortable"
          :formatter="item.formatter" />
      </template>

    </el-table>
  </div>
</template>

<script lang="jsx">
import { ref, defineComponent, getCurrentInstance, h } from 'vue' // 按需引入ref函数

import { Edit, Download, QuestionFilled, EditPen, Tickets, Delete } from '@element-plus/icons-vue'


export default defineComponent({
  name: 'JgTable',
  props: {
    description: {
      type: String,
      default: () => {
        return ' '
      }
    },
    tableDataObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
  },
  emits: ['update:editItem'],
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance()


    let tableData = ref({})
    let radioIndex = ref(null)

    watch([() => props.tableDataObj, () => props.rulesData], ([tableDataObj, rulesData]) => {
      // console.log('监听');
      tableData.value = proxy.$_.cloneDeep(tableDataObj) // 使用lodash的深拷贝方法

    }, { deep: true, immediate: true })


    function editItem(row, type) {
      console.log(row, type,);

      // 子传父
      emit('update:editItem', { row: row, type: type });
    }

    const myDiv = () => h('div', null, 'Hello, 1')

    // 多选
    const handleSelectionChange = (val) => {
      console.log(val);
      // 子传父
      emit('update:handleSelectionChange', val);
    }
    // 单选
    const changeRadio = (val) => {
      // console.log('单选', val, radioIndex.value.aa);
      emit('update:changeRadio', val);
    }

    // 表格点击事件
    const rowClick = (val) => {
      // console.log(val);
    }

    // 排序
    const sortChange = (val) => {
      // console.log(val);
      emit('update:sortChange', val);
    }




    // 将变量和函数返回,以便在模版中使用
    return {
      myDiv,
      radioIndex,

      tableData,

      editItem,
      handleSelectionChange,
      changeRadio,
      rowClick,
      sortChange,

      EditPen,
      Tickets,
      Delete,

    }
  }
})
</script>
<style lang="scss" scoped>
// 去除单选框的内容
:deep(.no-radio-label) {
  .el-radio__label {
    display: none;
  }
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/701582
推荐阅读
相关标签
  

闽ICP备14008679号