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')
            let _this = this
            this.sortable = new Sortable(el, {
                animation: 150,
                ghostClass: 'blue-background-class',
                direction: 'horizontal',
                forceFallback: true,
                onEnd: function (evt) {
                    // console.log('拖动前位置 : ' + evt.oldIndex)
                    // console.log('拖动后位置 : ' + evt.newIndex)
                    if (evt.newIndex === evt.oldIndex) {
                        return
                    }
                    // console.log('拖动前: ')
                    // console.log(_this.addVehicleOwnerForm.disabledGroupNameList.map(x => x.title))

                    const { oldIndex, newIndex } = evt
                    let newArr = JSON.parse(JSON.stringify(_this.addVehicleOwnerForm.disabledGroupNameList))
                    newArr.splice(newIndex, 0, newArr.splice(oldIndex, 1)[0])

                    _this.$set(_this.addVehicleOwnerForm, 'disabledGroupNameList', [])
                    _this.$nextTick(() => {
                        _this.$set(_this.addVehicleOwnerForm, 'disabledGroupNameList', newArr)
                        // console.log('拖动后: ')
                        // console.log(_this.addVehicleOwnerForm.disabledGroupNameList.map(x => x.title))
                    })
                }
            })
        },
        /**
             * @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
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 中,可以使用 `watch` 来监听数据的变化。如果你想要在表格中编辑字段,并且实时将编辑后的数据反映到组件中,可以使用以下步骤: 1. 在组件的 `data` 中定义一个数组,用于存储表格数据。 2. 在模板中使用 `v-for` 渲染表格,同时将每个单元格绑定到数组中对应的数据项。 3. 在每个单元格上添加一个 `@blur` 事件监听器,用于在编辑完成后触发保存操作。 4. 在 `methods` 中定义一个 `saveData` 方法,用于将编辑后的数据保存到数组中。 5. 在 `watch` 中监听数组的变化,并在数据变化时触发相应的操作。 以下是一个示例代码: ```html <template> <div> <table> <thead> <tr> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> </thead> <tbody> <tr v-for="(item, index) in tableData" :key="index"> <td> <input type="text" v-model="item.name" @blur="saveData" /> </td> <td> <input type="text" v-model="item.age" @blur="saveData" /> </td> <td> <select v-model="item.gender" @blur="saveData"> <option value="male">男</option> <option value="female">女</option> </select> </td> </tr> </tbody> </table> </div> </template> <script> export default { data() { return { tableData: [ { name: '张三', age: 18, gender: 'male' }, { name: '李四', age: 20, gender: 'female' } ] } }, methods: { saveData() { // 保存数据 } }, watch: { tableData: { handler(newVal, oldVal) { // 监听数据变化 }, deep: true } } } </script> ``` 在上面的示例中,我们定义了一个 `tableData` 数组来存储表格数据,然后在模板中使用 `v-for` 渲染表格。每个单元格都绑定到数组中对应的数据项,同时添加了一个 `@blur` 事件监听器。当用户编辑完单元格后,会触发 `saveData` 方法将编辑后的数据保存到数组中。在 `watch` 中监听 `tableData` 数组的变化,并在数据变化时触发相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值