vue2 ant-design记忆表头列表页面组件

git地址:项目git地址(https://github.com/hgg111/vue2AntdTablePage.git)
实现效果:
vue2 ant-design记忆表头列表页面组件_第1张图片
代码:
RemberTableHeader.vue组件: 记忆表头组件。将用户选择展示的表头数组存储在 localStorage 中,进入页面时读取,实现记忆表头功能。

<template>
    <div style="position: absolute;right: -5px;width: 30px;background-color: #f5f7fd;">
        <a-popover placement="bottomRight" :arrow="true">
            <a><a-icon type="setting">a-icon>a>
            <template slot="title">
                表头显示字段
            template>
            <template slot="content">
                <div style="max-height: 200px;overflow-y: auto;">
                    <div>
                        <a-checkbox value="all" :checked="checkedAll" @change="allChange">全选a-checkbox>
                    div>
                    <a-checkbox-group v-model="tableHeader" style="display:flex;flex-direction: column;align-items: flex-start;"
                        @change="tableHeaderChange">
                        <a-checkbox v-for="item in tableHeaderOptions" :key="item" :value="item">{{
                            item
                        }}a-checkbox>
                    a-checkbox-group>
                div>
            template>
        a-popover>
    div>
template>
<script>

export default {
    props: {
        // 表头
        allColumns: {
            type: Array,
            default: ()=>[],
        },
        // 表名(唯一)
        tableName: {
            type: String,
            default: ''
        },
        // 是否有报告操作列
        hasReportAction: {
            type: Boolean,
            default: false
        },
        // 是否有基本操作列
        hasAction: {
            type: Boolean,
            default: true
        },
        // 是否有序号列
        hasXuhao: {
            type: Boolean,
            default: true
        },
    },
    data() {
        return {
            // 全选框的状态
            checkedAll: true,
            // 所有可选择的表头
            tableHeaderOptions: [],
            // 选择的表头
            tableHeader: [],
            // 操作列内容
            actionContent: [],
            // 报告操作列内容
            reportActionContent: [],
            // 序号列内容
            xuhaoContent: [],
        };
    },
    watch:{
        allColumns: {
            handler(newVal) {
                if(newVal.length != 0){
                    Object.assign(this.allColumns,newVal)
                    this.init()
                }
            },
            deep: true,
            immediate: true
        },
    },
    mounted() {
        if(this.allColumns.length != 0){
            this.init()
        }
    },
    methods: {
        init() {
            this.tableHeaderOptions = []
            // 获取除了序号列和操作列的其他列
            this.allColumns.forEach(item => {
                if (item.title && item.title != '序号' && item.title != '报告操作' && item.title != '授权操作') {
                    this.tableHeaderOptions.push(item.title)
                }
                if (item.key == 'xuHao') {
                    this.xuhaoContent = item
                }
                if (item.key == 'reportAction' || item.key == 'authorization') {
                    this.reportActionContent = item
                }
                if (item.key == 'action') {
                    this.actionContent = item
                }
            })
            this.tableHeader = this.tableHeaderOptions
            // 从localStorage中获取当前表格之前存储的表头
            if (localStorage.getItem(this.tableName) != null) {
                this.tableHeader = localStorage.getItem(this.tableName).split(',')
                this.tableHeaderChange()
            }
            this.tableHeaderChange()
        },
        // 点击全选框
        allChange(value) {
            this.checkedAll = value.target.checked
            if (this.checkedAll == false) {
                this.tableHeader = []
            } else {
                this.tableHeader = this.tableHeaderOptions
            }
            this.tableHeaderChange()
        },
        // 表头选择改变
        tableHeaderChange() {
            // 向 localStorage 中存储当前选择的表头
            localStorage.setItem(this.tableName,this.tableHeader)
            var length = 2
            if(this.hasReportAction){
                length = 3
            }else if(!this.hasAction){
                length = 1
            }
            if(!this.hasXuhao){
                length -= 1
            }
            // 判断是否全选,设置选择框的选中状态
            if (this.tableHeader.length < this.allColumns.length - length) {
                this.checkedAll = false
            } else {
                this.checkedAll = true
            }
            var header = this.allColumns.filter(item => this.tableHeader.indexOf(item.title) > -1)
            // 向表头中添加序号列和操作列
            if(this.hasXuhao){
                header.unshift(this.xuhaoContent)
            }
            if(this.hasReportAction){
                header.push(this.reportActionContent)
            }
            if(this.hasAction){
                header.push(this.actionContent)
            }
            this.$emit('columnChange',header)
        },
    },
};
script>
<style>
.ant-checkbox-group :first-child {
    margin-left: 8px;
}
style>

记忆表头功能效果:
vue2 ant-design记忆表头列表页面组件_第2张图片

TablePage.vue:表格页面组件。页面包括树结构数据展示,树搜索,表格展示,表格筛选功能,并且实现响应式布局。

<template>
    <div id="page">
        <a-layout>
            
            <a-layout-sider v-if='treeDisplay'>
                <a-input-search v-if="hasTreeSearch" style="margin-bottom: 8px" placeholder="请输入名称"
                    @search="onSearch" />
                <a-tree expand-action="doubleclick" :tree-data="treeData" :expandedKeys="expandedKeys" defaultExpandAll
                    @select="select" @expand="onExpand" show-icon>
                    <template slot="title" slot-scope="{title}">
                        <span>{{ title }}span>
                    template>
                a-tree>
            a-layout-sider>
            <a-layout-content :class="{ 'tableContent': !treeDisplay }">
                <div classs="layout">
                    <div class="header">
                        <a-row>
                            <slot name="topOptionButton">slot>
                        a-row>
                        <a-row style="display: flex;justify-content: flex-end;align-items: center;margin-top: 5px;">
                            <slot name="filter">slot>
                        a-row>
                    div>
                    <div style="position: relative;">
                        <div class="setHeaderIcon">
                            <rember-table-header :allColumns="allColumns" :tableName="tableName" :hasReportAction="hasReportAction" :hasAction="hasAction"
                                        @columnChange="columnChange">rember-table-header>
                        div>
                        
                        <a-table id="tableDom" :columns="columns" :scroll="{ x: nowTableWidth,y: tableHeight}" :data-source="tableData"
                            :row-key="(record) => record.id ? record.id : record.taskId"
                            :row-selection="{ selectedRowKeys: tableSelectedRowKeys, onChange: onSelectChange, }"
                            :pagination="{ defaultPageSize: requestParams.pageSize, current: requestParams.pageNo, total: tableTotal, showTotal: (total) => `共 ${Math.ceil(total / requestParams.pageSize)} 页,共 ${total} 条数据`, }"
                            @change="pageCurrentChange">
                            <div slot="actionTitle">
                                <div style="display: flex;">
                                    <span>基本操作span>
                                div>
                            div>
                            <span class="indexColor resolveResult" slot="xuHao" slot-scope="record, id, index">
                                {{ (index + 1) + (requestParams.pageNo - 1) * requestParams.pageSize }}
                            span>
                            <a slot="name" slot-scope="text">{{ text }}a>
                            <div slot="action" slot-scope="text, record">
                                <a-space>
                                    <slot name="tableOpreation" :record="record">slot>
                                a-space>
                            div>
                        a-table>
                    div>
                div>
            a-layout-content>
        a-layout>
    div>
template>

<script>
import RemberTableHeader from '@/components/RemberTableHeader.vue'

export default {
    props: {
        // 表头
        allColumns: {
            type: Array,
            default: ()=>[],
        },
        // 树数据
        treeData: {
            type: Array,
            default: ()=>[],
        },
        // 表数据总数
        tableTotal: {
            type: Number,
            default: 0,
        },
        // 表数据
        tableData: {
            type: Array,
            default: ()=>[],
        },
        // 树结构是否展示
        treeDisplay: {
            type: Boolean,
            default: true
        },
        // 表选择项
        selectedRowKeys: {
            type: Array,
            default: ()=>[],
        },
        // 是否有其他操作项
        hasReportAction: {
            type: Boolean,
            default: false
        },
        // 是否有树搜索框
        hasTreeSearch: {
            type: Boolean,
            default: true
        },
        // 表名(用来存储,唯一)
        tableName: {
            type: String,
            default: ''
        },
        // 表格宽度
        tableWidth : {
            type: Number,
            default: 3200
        },
        // 表格高度
        tableHeight: {
            type: String,
            default: 'calc(100vh - 420px)'
        },
        // 是否有基本操作项
        hasAction: {
            type: Boolean,
            default: true
        },
    },
    data() {
        return {
            selectedStatusKeys: [],
            requestParams: {
                pageNo: 1,
                pageSize: 10
            },
            columns: this.allColumns,
            expandedKeys: [],
            searchValue: '',
            tableSelectedRowKeys: this.selectedRowKeys,
            nowTableWidth: 0,
            allTableWidth: 0
        };
    },
    watch: {
        selectedRowKeys: {
            handler(newVal) {
                this.tableSelectedRowKeys = newVal
            },
            deep: true,
            immediate: true
        },
        tableTotal: {
            handler() {
                this.requestParams.pageNo = 1
            },
            deep: true,
            immediate: true
        },
        allTableWidth(){
            this.getTableWidth()
        }
    },
    mounted() {
        this.expandedKeys.push('0')
        this.getTableData();
        this.getTreeData();
        // 延迟,等dom加载完毕,获取当前表格宽度
        setTimeout(() => {
            var tableDom = document.getElementById('tableDom')
            this.allTableWidth = tableDom.clientWidth - 20
        }, 100)
        // 响应式,分辨率改变时重新获取当前表格宽度
        window.addEventListener('resize',() => {
            var tableDom1 = document.getElementById('tableDom')
            if(tableDom1){
                this.allTableWidth = tableDom1.clientWidth - 20
                this.getTableWidth()
            }
        })
    },
    components: {
        RemberTableHeader
    },
    methods: {
        // 调用父组件函数获取表格数据
        getTableData(val) {
            if (val == 1) {
                this.requestParams.pageNo = 1;
            }
            this.$emit('getTableData', this.requestParams)
        },
        // 表格页码切换
        pageCurrentChange({ current }) {
            this.requestParams.pageNo = current;
            this.getTableData();
        },
        // 表格选中项改变
        onSelectChange(selectedRowKeys) {
            this.tableSelectedRowKeys = selectedRowKeys;
            this.$emit('getSelectedRowKeys', this.tableSelectedRowKeys)
            this.selectedStatusKeys = [];
            this.tableData.forEach(dt => {
                if (dt.status == 0) {
                    const filt = this.tableSelectedRowKeys.filter(ft => dt.id == ft)
                    if (filt && filt.length != 0) {
                        this.selectedStatusKeys.push(dt.id);
                    }
                }
            })
        },
        // 点击选择树结构
        select(selectId) { 
            this.$emit('select', selectId)
            if (selectId.length === 0) {
                return;
            }
            this.selectedKeys = selectId;
            this.tableSelectedRowKeys = [];
            if (selectId[0] == 'root') {
                this.selectedKeys = []
                return;
            }
            this.requestParams.pageNo = 1
            this.getTableData()
            this.total = 0
        },
        onExpand(expandedKeys) {
            this.expandedKeys = expandedKeys;
            this.autoExpandParent = false;
        },
        // 调用父组件函数获取树数据
        getTreeData(params) {
            this.searchValue = params;
            this.$emit('getTreeData', this.searchValue)
        },
        // 树搜索
        onSearch(value) {
            this.getTreeData(value)
        },
        // 展示列改变
        columnChange(columns) {
            this.columns = columns
            this.getTableWidth()
        },
        // 获取当前表格宽度
        getTableWidth() {
            var allColumnsWidth = 0
            // 获取当前所有列宽度之和,如果当前列没有设宽度则默认200 
            this.columns.forEach(item => {
                if(item.width){
                    allColumnsWidth += item.width
                }else{
                    allColumnsWidth += 200
                }
            })
            // 如果总列宽大于表格dom宽度,则取总列宽;如果总列宽小于表格dom宽度,则取表格dom宽度
            if (allColumnsWidth > this.allTableWidth) {
                this.nowTableWidth = allColumnsWidth
            } else {
                this.nowTableWidth = this.allTableWidth
            }
        },
    },
};
script>

<style lang="scss" scoped>
#page {
    padding: 20px;
}

.header {
    padding-bottom: 10px;
}

.tableContent {
    margin: 0;
}

.layout {
    background: #fff !important;

}

.ant-layout-sider {
    background: #fff;
    padding-right: 5px;
    border-right: 1px solid #eee;
}

.ant-layout-content {
    background: transparent;
    padding: 10px;
}

.ant-table-tbody {
    background: #fff !important;
    padding: 10px;
}

.outBoxStyle {
    background: blue !important;
}

.text {
    width: 100%;
    line-height: 15px;
    outLine: none;
}

/deep/.ant-table-fixed-header .ant-table-scroll .ant-table-header {
    background-color: #f5f7fd;
}

/deep/.ant-select-selection--multiple .ant-select-selection__rendered {
    height: 40px;
}

/deep/.ant-modal-body {
    max-height: 370px;
    overflow-y: auto;
}

/deep/.ant-table table {
    background-color: #f5f7fd;
}

/deep/.ant-transfer-customize-list .ant-transfer-list {
    width: 45%;
}

/deep/.ant-tree.ant-tree-block-node li span.ant-tree-checkbox+.ant-tree-node-content-wrapper {
    overflow: hidden;
    text-overflow: ellipsis;
}

/deep/.ant-table-fixed-header .ant-table-body-inner {
    background-color: #ffffff;
}

/deep/.ant-select-auto-complete.ant-select .ant-select-selection__rendered {
    line-height: 30px;
}

/deep/ .ant-table-thead>tr>th,
/deep/ .ant-table-tbody>tr>td {
    text-align: center;
}

/deep/.ant-table {
    height: calc(100vh - 300px);
}

/deep/.layout-dashboard .ant-tree {
    height: calc(100vh - 200px);
    overflow: scroll !important;
}

.setHeaderIcon{
    position: absolute;
    z-index: 999;
    right: 10px;
    top: 17px;
}
style>

实例 tableTest.vue

<template>
    <div id = 'page'>
        <table-page 
            :allColumns="columns" 
            :treeData="treeData" 
            :tableTotal="tableTotal"
            :tableData="tableData" 
            :treeDisplay="true" 
            :selectedRowKeys="selectedRowKeys"
            tableName="testTable"
            :tableWidth="1700"
            tableHeight="calc(100vh - 350px)"
            :hasTreeSearch="true"
            :hasReportAction="false"
            :hasAction="true"
            @getTableData="getTableData"
            @getTreeData="getTreeData"
            @getSelectedRowKeys="getSelectedRowKeys"
            @select="select"
            >
            
            <template v-slot:topOptionButton>
                <a-button type="primary" style="margin-right: 10px">新增a-button>
            template>
            
            <template slot="filter">
                <a-input placeholder="请输入名称" style="width: 120px;margin-right: 10px;">a-input>
                <a-input placeholder="请输入年龄" style="width: 120px;">a-input>
            template>
            
            <template v-slot:tableOpreation="itemProps">
                <a @click="editRecord(itemProps.record)">编辑a>
                <a-popconfirm title="确定删除?" ok-text="" cancel-text="" @confirm="() => deleteRecord(itemProps.record.id)">
                    <a class="deleText">删除a>
                a-popconfirm>
            template>
        table-page>
    div>
template>

<script>
import TablePage from '@/components/TablePage.vue'

const columns = [
    {
        title: "序号",
        scopedSlots: { customRender: "xuHao" },
        key:"xuHao",
        width: 80,
        fixed: 'left',
    },
    {
        title: '姓名',
        dataIndex: 'name',
        key: 'name',
    },
    {
        title: '年龄',
        dataIndex: 'age',
        key: 'age',
    },
    {
        title: '电话',
        dataIndex: 'phone',
        key: 'phone',
    },
    {
        title: '学历',
        dataIndex: 'education',
        key: 'education',
    },
    {
        title: '职业',
        dataIndex: 'occupation',
        key: 'occupation',
    },
    {
        title: '职业1',
        dataIndex: 'occupation1',
        key: 'occupation1',
    },
    {
        title: '职业2',
        dataIndex: 'occupation2',
        key: 'occupation2',
    },
    {
        title: '职业3',
        dataIndex: 'occupation3',
        key: 'occupation3',
    },
    {
        slots: { title: 'actionTitle'},
        key: 'action',
        scopedSlots: { customRender: 'action' },
        width: 100,
        fixed: 'right',
    },
]

export default{
    data(){
        return {
            tableData: [],
            tableTotal: 0,
            treeData: [],
            columns,
            selectedRowKeys: [],
            pageParams: {
                pageNo: 1,
                pageSize: 10
            }
        }
    },
    components:{
        TablePage
    },
    methods:{
        // 获取表格数据
        getTableData(params){
            if(params){
                this.pageParams.pageNo = params.pageNo
            }
            this.tableData = [
                {
                    id: 1,
                    name: '一',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 2,
                    name: '二',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 3,
                    name: '三',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 4,
                    name: '一',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 5,
                    name: '二',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 6,
                    name: '三',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 7,
                    name: '一',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 8,
                    name: '二',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 9,
                    name: '三',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 10,
                    name: '一',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 11,
                    name: '二',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                },
                {
                    id: 12,
                    name: '三',
                    age: 12,
                    phone: '12238746545',
                    education: '本科',
                    occupation: '学生'
                }
            ]
            this.tableTotal = this.tableData.length
        },
        // 获取树数据
        getTreeData(params){
            if(params){
                console.log("树搜索:",params)
            }
            this.treeData = [
                {
                    title: 'parent 1',
                    key: '0-0',
                    children: [
                        {
                            title: 'parent 1-0',
                            key: '0-0-0',
                            disabled: true,
                            children: [
                                {
                                    title: 'leaf1',
                                    key: '0-0-0-0',
                                    disableCheckbox: true,
                                },
                                {
                                    title: 'leaf2',
                                    key: '0-0-0-1',
                                },
                            ],
                        },
                        {
                            title: 'parent 1-1',
                            key: '0-0-1',
                            children: [
                                {
                                    title: 'leaf3',
                                    key: '0-0-1-0',
                                    disableCheckbox: true,
                                },
                                {
                                    title: 'leaf4',
                                    key: '0-0-1-1',
                                },
                            ],
                        },
                    ],
                },
            ]
        },
        // 表格选中项
        getSelectedRowKeys(selectedRowKeys){
            console.log("表格选中: ",selectedRowKeys)
        },
        // 编辑操作
        editRecord(record){
            console.log("编辑的表数据:",record)
        },
        // 删除操作
        deleteRecord(id){
            console.log("删除id为:",id,"的数据")
        },
        // 选择的树节点
        select(key){
            console.log("选择的树节点key:",key[0])
        }
    }
}
script>
<style>
body{
    background-color: rgb(207, 212, 212,0.42);
}
 #page{
    width: 100%;
    height: 100%;

 }

.ant-layout-sider{
    padding: 10px;
}
.deleText{
    color: red;
}
style>

你可能感兴趣的:(前端,vue.js,javascript,前端,vue2,ant-design)