基于vue和element-ui的表格组件,主推数据渲染,支持内容和方法灵活绑定,提供动态具名插槽自定义内容

        组件名为commonTable,主要是基于element-ui中的表格组件进行二次封装的组件,集成了常用的表格功能,除默认内容的显示外,还包括以下几点:

        1. 状态的筛选和显示;

        2. 操作按钮的显示和方法绑定;

        3. 自定义具名插槽内容的封装;

        4. 表格内容的翻页。

        除了提供的常用功能外,主要是希望可以通过组件的封装和应用,进一步理解和应用SPA框架主推的数据驱动理念,真正通过数据来描述页面应用。我们来看具体代码:

        应用实例:

<!-- 表格组件 -->
    <CommonTable :tableData="tableData" :tableConfig="tableConfig" :pageConfig="pageConfig"></CommonTable>

         组件包含三个主要参数,分别是:

        tableData:表格组件的数据内容,通常通过后端接口获取;

// 表格数据内容
        tableData: [
            {
                "id": "001",
                "name": "小明",
                "sex": 1,
                "address": "北京市"
            },
            {
                "id": "002",
                "name": "小红",
                "sex": 2,
                "address": "上海市"
            }
        ],

        tableConfig:表格组件的配置,通过这个配置,组件自动生成表格;

// 表格配置
        tableConfig: [
          {
              label: "名称",
              prop: "name",
              sortable: true,
          },
          {
              label: "性别",
              prop: "sex",
              type: "status",
              callback: (scope) => {
                switch(scope.row.sex) {
                  case 1 :
                    return {
                      text: '男',
                      color: 'blue'
                    }
                  case 2 :
                    return {
                      text: '女',
                      color: 'red'
                    }
                }
              }
          },
          {
              label: "地址",
              prop: "address",
              type: "slot"
          },
          {
              label: "操作",
              prop: "operate",
              type: "operate",
              operateList: (scope) => {
                return [
                  {
                    text: "编辑",
                    callback: (scope) => {console.log("编辑"+scope.row)}
                  },
                  {
                    text: "删除",
                    color: "red",
                    callback: () => {console.log("删除"+scope.row)}
                  },
                ]
              }
          },
        ],

        pageConfig:表格组件的分页配置,翻页等方法也都在这里配置,如果不写,默认没有分页功能。

// 分页配置
        pageConfig: {
          sizeChange: (val) => {console.log('sizeChange--'+val)},
          currentChange: (val) => {console.log('currentChange--'+val)},
          pageSizes: [10, 20, 50],
          layout: "total, prev, pager, next, sizes",
          pageSize: 10,
          total: 100,
          currentPage: 1
        }

       表格主要分为四种不同类型的内容,通过type来区分不同类型,当没有type值的时候,就传入默认的数据内容,下面详细看下代码:

1. 自定义类型:(type: slot)

        通过vue的具名插槽的功能,在组件中插入同名的插槽,插槽名为prop属性内容,插槽内容可以自定义,通过scope传入表格当前行的数据来进行数据操作。vue提供了一个方法来进行动态的具名插槽绑定,用v-slot动态绑定插槽名。

<!-- 示例 -->
    <CommonTable :tableData="tableData" :tableConfig="tableConfig" :pageConfig="pageConfig">
        <template v-slot:self="{ scope }">
            <div>{{ scope.row }}</div>
        </template>
    </CommonTable>
<!-- 自定义类型 -->
          <el-table-column
            v-if="item.type === 'slot'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <slot :name="item.prop" :scope="scope"></slot>
            </template>
          </el-table-column>

2.状态类型:(type: status)

        表格中经常会用到一些用来标识状态的标签,例如性别、身份等。并且经常会遇到需要对后端接口提供的数据进行转义,例如等于1的时候是男性,等于2的时候是女性。可以在组件中提前封装好需要的状态类型标签,并且内容和颜色,可以通过text和color两种属性来自由搭配。保证了全局标签样式的统一性的同时,也提供了一定的可自定义化。

<!-- 状态类型 -->
          <el-table-column
            v-if="item.type === 'status'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <span v-if="item.callback(scope).color === 'blue'" class="status-label label-blue">{{ item.callback(scope).text }}</span>
              <span v-if="item.callback(scope).color === 'red'" class="status-label label-red">{{ item.callback(scope).text }}</span>
              <span v-if="!item.callback(scope).color">{{ item.callback(scope).text }}</span>
            </template>
          </el-table-column>

 3. 操作类型:(type: operate)

        表格最后一列通常包含相应的操作,例如编辑、删除等。在组件中封装好操作类型,在使用的时候可以灵活搭配操作按钮的展示内容和绑定的方法。operateList返回按钮列表,通过名为show的属性可以根据不同的条件应用不同的按钮,通过callback属性来绑定按钮的方法。

<!-- 操作类型 -->
          <el-table-column
            v-if="item.type === 'operate'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <template v-for="(operateItem, operateIndex) in item.operateList(scope)">
                <span
                  v-if="operateItem.show === undefined || operateItem"
                  :key="operateIndex"
                  @click="operateItem.callback(scope)"
                  :class="['operate-button', operateItem.color === 'red' ? 'operate-red' : '']">{{ operateItem.text }}</span>
              </template>
            </template>
          </el-table-column>

4. 默认类型:(type: none)

        当type值不存在的时候,默认展示prop属性对应的表格数据内容。

<!-- 默认类型 -->
          <el-table-column
            v-if="!item.type"
            :key="index+index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable"
            :show-overflow-tooltip="true">
            <template slot-scope="scope">
              <span>{{ scope.row[item.prop] }}</span>
            </template>
          </el-table-column>

        总结一下,在element-ui的table组件和pagination组件的基础上进行封装,以达成全局数据驱动渲染表格内容,实现表格展示和操作的目的。

四种类型分别是

        自定义类型标签类型操作类型和默认类型

三个主要参数是

        tableData(数据内容)tableConfig(表格配置)pageConfig(分页配置)

属性说明:

        1. 通过label属性或者text属性参数来展示表格需要显示的内容;

        2. 通过prop属性来绑定对应数据的字段名;

        3. 通过show属性来绑定内容是否显示的条件,通过color属性绑定内容样式;

        4. 通过callback属性绑定需要的操作方法,callback中的scope参数绑定当前数据内容。

组件优势:

        全局数据驱动,统一表格组件的同时,提供了表格展示内容和操作方法的灵活绑定,并提供了动态具名插槽进行内容自定义。

看下渲染后的效果:

最后附上完整组件代码:

<template>
    <div class="common-table">
      <el-table
        :stripe="stripe"
        :height="height"
        :data="tableData"
        :config="tableConfig"
        empty-text="暂无数据">
        <template v-for="(item, index) in tableConfig">
          <!-- 自定义类型 -->
          <el-table-column
            v-if="item.type === 'slot'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <slot :name="item.prop" :scope="scope"></slot>
            </template>
          </el-table-column>

          <!-- 状态类型 -->
          <el-table-column
            v-if="item.type === 'status'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <span v-if="item.callback(scope).color === 'blue'" class="status-label label-blue">{{ item.callback(scope).text }}</span>
              <span v-if="item.callback(scope).color === 'red'" class="status-label label-red">{{ item.callback(scope).text }}</span>
              <span v-if="!item.callback(scope).color">{{ item.callback(scope).text }}</span>
            </template>
          </el-table-column>

          <!-- 操作类型 -->
          <el-table-column
            v-if="item.type === 'operate'"
            :key="index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable">
            <template slot-scope="scope">
              <template v-for="(operateItem, operateIndex) in item.operateList(scope)">
                <span
                  v-if="operateItem.show === undefined || operateItem"
                  :key="operateIndex"
                  @click="operateItem.callback(scope)"
                  :class="['operate-button', operateItem.color === 'red' ? 'operate-red' : '']">{{ operateItem.text }}</span>
              </template>
            </template>
          </el-table-column>

          <!-- 默认类型 -->
          <el-table-column
            v-if="!item.type"
            :key="index+index"
            :prop="item.prop"
            :width="item.width"
            :label="item.label"
            :sortable="item.sortable"
            :show-overflow-tooltip="true">
            <template slot-scope="scope">
              <span>{{ scope.row[item.prop] }}</span>
            </template>
          </el-table-column>

        </template>

      </el-table>

      <!-- 分页 -->
      <el-pagination
        v-if="pageConfig"
        class="table-page"
        @size-change="pageConfig.sizeChange"
        @current-change="pageConfig.currentChange"
        :page-sizes="pageConfig.pageSizes"
        :layout="pageConfig.layout || 'total, prev, pager, next, sizes'"
        :page-size="pageConfig.pageSize"
        :current-page="pageConfig.currentPage"
        :total="pageConfig.total">
      </el-pagination>
    </div>
  </template>
  
  <script>
    export default {
      props: {
        tableConfig: {
          type: Array,
          default: () => []
        },
        tableData: {
          type: Array,
          default: () => []
        },
        pageConfig: {
          type: Object,
          default: () => {}
        },
        stripe: {
          type: Boolean,
        },
        height: {
          type: String,
        },
      },
      data () {
        return {}
      },
      mounted() {
      },
      methods: {
      }
    }
  </script>
  
  <style lang="scss">
    .operate-button {
      display: inline-block;
      margin-right: 5px;
      color: #09f;
      &:hover {
        cursor: pointer;
      }
    }
    .operate-red {
      color: #f00;
    }
    .status-label {
      display: inline-block;
      width: 60px;
      height: 25px;
      text-align: center;
      line-height: 25px;
      border-radius: 5px;
    }
    .label-blue {
      background: rgba(164, 205, 245, 0.5);
      color: #0888de;
      border: 1px solid #0888de;
    }
    .label-red {
      background: rgb(240 141 181 / 50%);
      color: #de083a;
      border: 1px solid #de083a;
    }
  </style>
  

文章来源地址https://uudwc.com/A/y54Ym/

原文地址:https://blog.csdn.net/kakashi_chen/article/details/129901186

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年11月02日 13:20
基于matlab创作简易表白代码
下一篇 2023年11月02日 14:50