vue+element-ui table表格封装之操作列,操作组件

7,431 阅读3分钟

一般来说,table的某一列需要有可以对当前行进行操作的多个按钮,不管是编辑查看还是上传下载。这部分的实现很多人都写过,这里的写法是将操作的这个部分抽离出来,单独做一个组件,每次只需要传操作的类型和对应的处理函数就可以。涉及到很多表格的系统,比如后台管理系统,这样的组件就方便很多。

table-operation组件

首先创建这个操作部分的组件,这个组件其实很简单,就是一个<el-button-group>包裹了一些<el-button>,这些按钮通过循环父组件传来的operation数组渲染,operation是一个只有按钮类型和按钮上显示的文字两个字段的数组。整个组件的代码如下:

<template>
    <el-button-group>
        <el-button
          v-for="(op,index) in operations"
          :key="index"
          type="primary"
          size="mini"
          :icon="icons[op.type]"
          @click="clickOperation(op)"
        >{{op.title}}</el-button>
    </el-button-group>
</template>

<script>
export default {
    name: 'TableComponent',
    props: {
    operations: {
        type: Array
    },
    rawData: {
        type: Object
    }
    },
    data () {
        return {
            icons: {
                edit: 'el-icon-edit',
                view: 'el-icon-view'
            }
        };
    },
    methods: {
        clickOperation (operation) {
            this.$emit('handleOperation',operation,this.rawData);
        }
    }
};
</script>

icons可以规定特定类型的按钮要对应哪种图标

使用el-table的组件中

此处这个组件叫它table-page,只看<el-table>的部分

<el-table
    :data="list"
    class="mt-10"
    fit
    stripe
    empty-text="暂无数据"
    :highlight-current-row="true"
    >
        <el-table-column
            v-for="(item, index) in table_title"
            :key="index"
            :prop="item.prop"
            :label="item.label"
            :width="item.width?item.width:null"
            :min-width="item.minwidth?item.minwidth:null"
            :sortable="item.sortable?item.sortable:false"
            :align="item.columnAlign"
            :header-align="item.titleAlign"
        >
            <template slot-scope="scope">
                <template v-if="item.tag">
                    <slot name="tags" :scope="scope.row"></slot>
                </template>
                <span v-else>{{scope.row[item.prop]}}</span>
            </template>
        </el-table-column>
        <!-- 如果需要自定义最后一栏则需传入operates对象,并提供模板 -->
        <el-table-column v-if="operates.operate" 
            :label="operates.label" 
            :width="operates.width"
            :align="operates.columnAlign"
            :header-align="operates.titleAlign">
            <template slot-scope="scope">
                <slot name="operates" :scope="scope"></slot>
            </template>
        </el-table-column>
    </el-table>

可以看到在循环完其他的table数据以后,最后一列渲染出来是一个操作列,此处需要接受来自父组件的operates对象,这是一个和其他属性数组的每一项相似的列,其实完全可以和其他写在一起,用v-if来判断(就像上面的tag列似的),这里为了特别说明单独抽出来,放置一个插槽以方便我们使用操作组件。

使用以上两个组件的父组件

在这个父组件中,首先看一下上面所说的传给两个子组件的operationoperates的定义

const operates = {
  operate: true,
  label: '操作',
  minwidth: '120px',
  titleAlign: 'center',
  columnAlign: 'center',
};

const operations = [
  {
    type: 'edit',
    title: '编辑'
  },
  {
    type: 'view',
    title: '查看'
  }
];

怎么用这两个组件呢

<table-page
    :list="list"
    :table_title="table_title"
    :operates="operates"
    >
    ...// 其他的templates
    <template v-slot:operates="scope">
        <table-operation 
            :operations="operations"
            :rawData="scope.scope.row"
            @handleOperation="handleOperation"
        ></table-operation>
    </template>
</table-page>

可以看到给<table-page>传了一个operates,给<table-operation>传了一个operation和一个处理操作的函数,这里就是填了之前空出来的插槽,放置这个操作的组件。

那么这个处理操作的函数做了些什么事情呢?

methods: {
    ...,
    handleOperation(op,row) {
        if (op.type == 'edit') {
            // 编辑它
        }
        else if (op.type == 'view') {
            // 看看它
        }
    },
    ...
}

在操作组件中,我们也可以看到给这个函数回传了两个参数,分别是操作组件的这一项以及这一行数据。这两个拿到的话应该能解决大多数场景的问题。根据optype来判断触发的是哪一个按钮,然后做出对应的操作就可以,比如弹一个<el-dialog>出来~

呈现效果

点击编辑:

就可以愉快编辑了!