IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> VUE动态展示表格字段 -> 正文阅读

[JavaScript知识库]VUE动态展示表格字段

前言

最近叼毛产品让写个需求,动态展示表格字段,要求动态根据用户习惯保存,下次进页面展示以前的,还能再次选择。

思考

  • 让用户选择展示那些字段
  • 保存db
  • 进页面先查询db 然后根据table 字段属性过滤

平时vue页面写的表格类型字段


 columnsData: [
                {
                    title: '状态',
                    width: 120,
                    align: 'center',
                    key: 'a',

                    render: (h, params) => {
                        const row = params.row
                        return 'xxxxxx'
                    },
                    filters: [

                        {
                            label: 'xxx',
                            value: 1
                        },
                        {
                            label: 'xxxx',
                            value: 2
                        },
                        {
                            label: 'xxxx',
                            value: 3
                        }
                    ],
                    filterMultiple: true,
                    filterRemote(value) {
                        this.queryForm.a = value.join(',')
                        this.search()
                    }
                },
                {
                    title: 'xxxx',
                    width: 100,
                    align: 'center',
                    key: 'b',
                    filters: [

                        {
                            label: 'xxx',
                            value: 1
                        },
                        {
                            label: 'xxx',
                            value: 2
                        }

                    ],
                    filterMultiple: false,
                    filterRemote(value) {
                        this.queryForm.b = value[0]
                        this.search()
                    },
                    render: (h, params) => {
                        const row = params.row
                        if (row.payType === 1) {
                            return 'xxx'
                        }
                        return 'xxx'
                    }
                },
                {title: '时间', width: 120, key: 'c', sortable: 'custom'},

在页面加载时候会吧次数据加载到内存,我们用次定义的字段,展示列表,让用户选择,需要展示的那些字段。

核心数据已打码

在这里插入图片描述

选择的数据保存到db即可
这里需要注意的是 根据自己需求保存,是保存字段还是保存数组下标。

  • 保存字段,可能会有重复字段(定义重复字段)
  • 保存下标,表格属性head可能会被修改(中间肯能添加,导致保存数据和元数据不一致)

这里建议保存字段

实现

表设计

这里我们根据用户手机号保存,当然其他条件自己可以扩展。
在这里插入图片描述

考虑到别的表格字段可能也需要,便于扩展,将次写成组件,易于其他页面扩展。

第一步 查询后台配置

有配置则展示配置字段,否则展示原有字段

http查询后台字段 (这里需要注意的是查询时候必须先查询此配置,再查询后台表格数据,必须同步查 )

  代码就不展示了
  一个查询即可

这里content 我用,号拼接保存的字段

a,b,c,d,e 然后用此和原有的字段进行对比

查询



data(){

               initColumnList: [], //备份
                backupInitColumnList: [],//备份

//组件传入值
                tableFiledForm: {
                    show: false,
                    tableType: 5, //类型 那个table page
                    originTableFiledList: [],  //穿进去的默认table 字段
                    columnList: []  //db中原先选中的字段
                }
},
   created() {
   //这里可以会根据 配置考虑是否要拷贝
            this.deepInit().then(() => {  //拷贝 
                this.getTableFiled(5).then(() => {  //查询配置
                    this.search()  //查询表格数据
                })
            })
            }

查询配置

这里后台代码就省略了,也没啥写的、

//查询配置 
            getXXXXXXXXX(type) {
                return new Promise((resolve, reject) => {
                    this.tableFiledForm.columnList = this.initColumnList
                    let params = {
                        method: 'get',
                        url: this.$context + '/table/getTable?=' + type
                    }
                    this.$http(params)
                        .then(res => {
                            if (res.data.code === '200' && res.data.data !== null && res.data.data !== '') {
                                let columnsDataArray = this.initColumnList
                                let originTableFiledList = res.data.data.content.split(',')
                                let originTableFiledListElement = originTableFiledList.filter(x => x !== '')
                                if (originTableFiledListElement.length === 0) {
                                    this.columnsData = this.backupInitColumnList
                                    return
                                }
                                //将从db查询的字段 组装好赋值给 columnsData,columnsData 也就是表格上的 字段数组
                                this.columnsData = this.tablefiledJS.sortAndFilter(columnsDataArray, originTableFiledListElement)
                            }
                        })

                    resolve()
                })
            },
        

查询完之后进行原有的展示字段备份

这里需要注意的是,原有的字段,我们可能会定义函数,拷贝的时候需要将函数也一同拷贝了。

    //深拷贝 
            deepInit() {
                return new Promise((resolve, reject) => { //同步
                    // copy original columnsData to tableFiledForm
                    for (let i = 0; i < this.columnsData.length; i++) {
                        let columnsDatum = this.columnsData[i]
                        let deepCopyList1 = this.tablefiledJS.deepCopy(columnsDatum)
                        let deepCopyList2 = this.tablefiledJS.deepCopy(columnsDatum)
                        this.initColumnList.push(deepCopyList1) //备份字段  在没查询到的时候 使用原字段
                        this.backupInitColumnList.push(deepCopyList2) //备份字段
                    }
                    resolve()
                })
            },

选中后(或者进页面根据选中的字段,进行过滤字段)

//深拷贝 工具
var deepCopy = function deepCopy(obj) {
    let result = obj
    if (typeof obj === 'object' && obj !== null) {
        result = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {}
        for (let prop in obj) {
            result[prop] = this.deepCopy(obj[prop])
        }
    }
    return result
}

const operation = '操作'
const selection = 'selection'
//排序和 从元组件里获取db保存字段的属性
// db 中保存 a,b  
// 原table 属性中  可参考最上面定义的表格字段
// columnsDataArray  从Db查的字段数组  分割 a,b => [a,b]   
// originTableFiledList 原table 属性字段
var sortAndFilter = function sortAndFilter(columnsDataArray, originTableFiledList) {
    let array = []
    let sortArray = []
    for (let i = 0; i < columnsDataArray.length; i++) {
        let columnsDataObj = columnsDataArray[i]
        if (columnsDataObj.type === selection) {
            array.push(columnsDataObj)
        }

        if (!columnsDataObj.key || columnsDataObj === '') {
            continue
        }
        for (let ii = 0; ii < originTableFiledList.length; ii++) {
            if (columnsDataObj.key === originTableFiledList[ii]) {
                array.push(columnsDataObj)
                continue
            }
        }

        if (columnsDataObj.title === operation) {
            array.push(columnsDataObj)
        }
    }

    if (array.len !== 0) {
        console.log('sort befor : ')
        console.log(array)
        var jsonAarry = array.filter(x => x.title === operation)
        if (array.length <= originTableFiledList.length / 2) {
            for (let i = array.length - 1; i >= 0; i--) {
            	//过滤不需要的 复选框 类型  这里根据自己需要
                if (array[i].type === selection) {
                    continue
                }
                delete array[i].width
            }
            // 防止没有`操作`
            if (jsonAarry.length > 0) {
                delete jsonAarry[0].fixed
            }
        }

        let selectionJson = array.filter(x => x.type === selection)
        if (selectionJson.length > 0) {
            sortArray.push(selectionJson[0])
        }
        // sort 排序成db保存的类型 对应 拖拽组件的排序
        for (let k = 0; k < originTableFiledList.length; k++) {
            for (let p = 0; p < array.length; p++) {
                if (array[p].key === originTableFiledList[k]) {
                    if (!sortArray.find(x => x.key === originTableFiledList[k])) {
                        sortArray.push(array[p])
                        continue
                    }
                }
            }
        }
        let json = array.filter(x => x.title === operation)
        if (json.length > 0) {
            sortArray.push(json[0])
        }

        this.columnsData = sortArray
        console.log('after sort : ')
        console.log(sortArray)
    }
    return sortArray
}
export default {
    sortAndFilter,
    deepCopy
}

表格页面 引入组件


      <tableFiled
          :show="tableFiledForm.show"  // 是否展示
          :columnList="tableFiledForm.columnList" //原字段 组件页面点击选择
          :tableType="tableFiledForm.tableType"  //类型  那个表格的类型
          @closeConfirmOrder="confirmTableFildeForm"  // 关闭
          @getSearch="getTableFiled(5)"     //保存回调查询
      ></tableFiled>

组件关闭和展示

        //组件弹框 显示和关闭
            confirmTableFildeForm() {
                this.tableFiledForm.show = false
            },
            disabledTableFiled() {
                this.tableFiledForm.show = true
            }

table页面点击展示选择字段的按钮

<span @click="disabledTableFiled"> 点击打开页面选择,字段</span>

在这里插入图片描述

组件代码

<template>
    <Modal
            v-model="show"
            :mask-closable="false"
            :closable="false"
            :columnList="columnList"
            :tableType="tableType"
            :originTableFiledList="originTableFiledList"
            width="800"
            :title="modeMapper[mode]">
        <Form ref="addTableFieldFormLimit" :model="addVehicleOwnerForm">
            <Row>
              <div style="height: 300px;">
                <template>
                  <div style="width: 74%;display: inline-block;height: 280px;overflow-y:scroll;">

                    <Checkbox-group v-model="addVehicleOwnerForm.disabledGroup" @on-change="watchCheck()">
                        <div v-for=" (it,index) in addVehicleOwnerForm.tableFieldList" style="display: inline-block;margin-left: 5px;margin-top: 2px;width: 120px;">
                          <Checkbox :label="index"> <span style="margin-left: 5px"> </span>{{it.title}}</Checkbox></div>
                        <br v-if="(index + 1) % 4 ===0">
                    </Checkbox-group>
                  </div>
                  <div style="width: 25%;display: inline-block;height: 300px;overflow-y:scroll;">
                    <h5 style="margin-left: 5px;margin-top: 2px;">当前已选字段</h5>

                    <div style="margin-top: 20px;">
                      <div id="example1" class="list-group col" >
                        <div  class="list-group col" v-for=" (it,index) in addVehicleOwnerForm.disabledGroupNameList" style="margin-top:10px;">
                          <span style="margin-top: 20px;margin-left:10px"><img src="../../../images/tdimg.png" width="13xp" height="13px" > </span><span style="margin-left: 15px;"> {{it.title}}</span> <span style="margin-left: 10px;" @click="deleteVoid(index)"><img src="../../../images/gb.png" width="13xp" height="13px" ></span>
                        </div>
                      </div>
                    </div>
                  </div>


                </template>
              </div>
            </Row>
        </Form>
        <!-- 自定义footer -->
        <div slot="footer">
            <Button @click="cancelHandle">取消</Button>
            <Button type="primary" @click="addVehicleOwnerHandle">确定</Button>
        </div>
    </Modal>
</template>

<script>
//拖拽排序的 插件  
import Sortable from 'sortablejs'

export default {
    data() {
        return {
            addVehicleOwnerForm: {
                disabledGroup: [], //选中的组件
                tableFieldList: []  // 所有字段(表格原有的字段,展示列表  让用户点击选择)
            },
            disabledGroupNameList: [],
            sortable: null,
            modeMapper: {
                add: '设置列表显示字段',
                edit: '设置列表显示字段'
            },
            loading: false
        }
    },
    props: {
    //组件传进来的值
        show: {type: Boolean, require: true},
        mode: {type: String, default: 'add'},
        originTableFiledList: {type: Array, default: []},
        tableType: {type: Number},
        columnList: {type: Array, default: []}
    },
    methods: {

        filterTableFieldMethod() {
            console.log('this.columnList : ')
            console.log(this.columnList)
            let columnsDataArray = this.columnList
            let array = []
            for (let i = 0; i < columnsDataArray.length; i++) {
                let columnsDataObj = columnsDataArray[i]
                //过滤操作,默认表格展示的操作 和 选择框  这里我进行了过滤
                if (columnsDataObj.type === 'selection' || columnsDataObj.title === '操作') {
                    continue
                }
                array.push(columnsDataObj)
            }

            this.addVehicleOwnerForm.tableFieldList = array

            // this.addVehicleOwnerForm.disabledGroup = [0, 1]
            // 查询后台是否被选中
            let checked = this.savedFieldId()
            this.getDisabledGroupNameList()
            this.addVehicleOwnerForm.disabledGroup = checked
            console.log(' save index ')
            console.log(this.addVehicleOwnerForm.disabledGroup)
            this.addVehicleOwnerForm.tableType = this.tableType

            this.initSortable()
        },
        savedFieldId() {
            let checked = []
            let params = {
                method: 'get',
                url: this.$context + '/table/getTable?tableType=' + this.tableType
            }
            this.$http(params)
                .then(res => {
                    if (res.data.code === '200' && res.data.data !== null && res.data.data !== '') {
                        let originTableFiledList = res.data.data.content.split(',')
                        // saved field
                        for (let j = 0; j < originTableFiledList.length; j++) {
                            for (let i = 0; i < this.addVehicleOwnerForm.tableFieldList.length; i++) {
                                if (originTableFiledList[j] === this.addVehicleOwnerForm.tableFieldList[i].key) {
                                    checked.push(i)
                                }
                            }
                        }
                    }
                })

            return checked
        },
        /**
             * @description 取消
             */
        cancelHandle() {
            this.$emit('closeConfirmOrder', []) // 关闭模态窗
        },
        deleteVoid(val) {
            if (this.addVehicleOwnerForm.disabledGroup.length === 1) {
                this.addVehicleOwnerForm.disabledGroup = []
                this.addVehicleOwnerForm.disabledGroupNameList = []
                return
            }
            this.addVehicleOwnerForm.disabledGroup.splice(val, 1)
        },
        watchCheck() {
            if (this.addVehicleOwnerForm.disabledGroup.length === 0) {
                this.addVehicleOwnerForm.disabledGroupNameList = []
            }
        },
        // 初始化拖拽 拖拽排序
        initSortable() {
            const el = document.querySelector('#example1')
            this.sortable = new Sortable(el, {
                animation: 150,
                ghostClass: 'blue-background-class',
                direction: 'horizontal',
                forceFallback: true,
                onEnd: ({newIndex, oldIndex}) => {
                    var oldArrayIndex = 0
                    var newArrayIndex = 0
                    for (let i = 0; i < this.addVehicleOwnerForm.disabledGroup.length; i++) {
                        if (newIndex === i) {
                            newArrayIndex = i
                        }
                        if (oldIndex === i) {
                            oldArrayIndex = i
                        }
                    }
                    var oldobj = this.addVehicleOwnerForm.disabledGroup[oldArrayIndex]
                    var newobj = this.addVehicleOwnerForm.disabledGroup[newArrayIndex]
                    this.addVehicleOwnerForm.disabledGroup[oldIndex] = newobj
                    this.addVehicleOwnerForm.disabledGroup[newIndex] = oldobj
                }
            })
        },
        /**
             * @description 确定
             */
        addVehicleOwnerHandle() {
            if (this.addVehicleOwnerForm.disabledGroup.length === 0) {
                this.$Message.info('未选择使用默认字段')
                this.sendHttp('')
                return
            }

            if (this.addVehicleOwnerForm.disabledGroup.length < 4) {
                this.$Message.info('至少选择4个!')
                return
            }

            if (this.addVehicleOwnerForm.disabledGroup.length === this.addVehicleOwnerForm.tableFieldList.length) {
                this.$Message.info('不能全选')
                return
            }

            let tableFieldStr = ''
            for (let disabledGroupElement of this.addVehicleOwnerForm.disabledGroup) {
                for (let j = 0; j < this.addVehicleOwnerForm.tableFieldList.length; j++) {
                    if (disabledGroupElement !== j) {
                        continue
                    }
                    tableFieldStr += ',' + this.addVehicleOwnerForm.tableFieldList[j].key
                }
            }
            console.log(this.addVehicleOwnerForm.disabledGroup)
            console.log(tableFieldStr)

            this.sendHttp(tableFieldStr)
        },
        sendHttp(tableFieldStr) {
            // 配置请求参数
            let params = {
                method: 'post',
                url:  '127.0.0.1:9090table/add',
                data: {
                    'tableType': this.tableType,
                    'content': tableFieldStr
                }
            }
            // 发送请求
            this.$http(params)
                .then(res => {
                    this.$Message.success(res.data.msg) // 提示成功
                    this.$emit('closeConfirmOrder', []) // 关闭模态窗
                    this.$emit('getSearch') // 关闭模态窗
                })
        },
        getDisabledGroupNameList() {
            let array = []
            for (let disabledGroupElement of this.addVehicleOwnerForm.disabledGroup) {
                for (let j = 0; j < this.addVehicleOwnerForm.tableFieldList.length; j++) {
                    if (disabledGroupElement !== j) {
                        continue
                    }
                    array.push(this.addVehicleOwnerForm.tableFieldList[j])
                }
            }
            this.addVehicleOwnerForm.disabledGroupNameList = array
        }
    },
    watch: {
        columnList(val) {
            if (val.length) {
                this.filterTableFieldMethod()
            }
        },
        'addVehicleOwnerForm.disabledGroup': function (val) {
            if (val.length !== 0) {
                this.getDisabledGroupNameList()
            }
        }
    },
    created() {
        this.filterTableFieldMethod()
    }
}
</script>

演示

选择字段

在这里插入图片描述

在这里插入图片描述

保存后table展示字段
在这里插入图片描述

最后

  • 注意深拷贝,原先字段定义的函数也需要拷贝过来
  • 拖拽排序组件
  • 可参考
    http://www.sortablejs.com/index.html
    https://www.cnblogs.com/moqiutao/p/6423754.html
    https://blog.csdn.net/wsln_123456/article/details/108595514
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:03:16  更:2022-03-03 16:03:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:12:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码