vue实现复杂的表单Dom操作

2023-02-15  本文已影响0人  毕竟1米八

春节过后公司需要上线一个抽奖优惠活动,在后台管理页面中涉及到表单的动态添加、修改dom等复杂操作。开发的过程中遇到许多的知识点和困难点,于是总结了以下一些技巧经验。

一、业务需求

如图所示,在抽奖页面中,涉及到获取奖品、添加奖品、修改奖品、删除奖品(增删改查)、上传图片等功能。

二、vue版本
基于vue2.x语法和element-ui框架。

三、难点分析

四、关键代码实现

// data数据
lotteryList: [
                // {
                //     hl_name: "",
                //     hl_type: null,
                //     hl_days: "",                                                                                                                                                    
                //     hl_lnums: "", //库存
                //     hl_shownum: "", //展示数量
                //     hl_img: "",
                //     isImgUpload: false, // 上传图片开关 前端加的判断
                //     isEdit: false, // 是否编辑状态 前端加的判断
                //     hl_lucky: true, // 1开 2关 提交的时候需要转换一下
                //     hl_rate: "", // 概率
                // },
            ],
            watchLotteryList: [], // 用来监听列表的数据变化
            originLotteryList: [],  // 源数据 深拷贝后的
            curIndex: null

// 动态添加dom
onAdd() {
            // 默认追加的dom数据是没有id的 因此根据id来区别真假数据
            this.lotteryList.push({
                hl_name: "",
                hl_type: null,
                hl_days: "",
                hl_lnums: "",
                hl_shownum: "",
                hl_img: "",
                isImgUpload: false, // 前端加的判断
                isEdit: false, // 前端加的判断
                hl_lucky: true,
                hl_rate: "",
            });
        },
// 获取抽奖列表
        getList() {
            getLottery({}).then(res => {
                console.log('res: ', res);
                if(res.state == 0){
                    if (res.data) {
                        let data = res.data
                        data.filter(item => {
                            item.hl_type = Number(item.hl_type)  // 需要number类型 否则el-select不会回显
                            item.hl_lucky = item.hl_lucky == 1 ? true : false;
                            item.isEdit = false // 追加一个编辑状态
                        })
                        console.log('data: ', data);
                        this.lotteryList = data
                        
                        // this.watchLotteryList = JSON.parse(JSON.stringify(data))
                        // 保持一份初始数据 不被双向绑定给影响到
                        this.originLotteryList = JSON.parse(JSON.stringify(data))
                        // 这一份数据用来监听列表数据的 因为直接监听lotteryList再修改原数据lotteryList会造成监听无限执行
                        this.watchLotteryList = data
                    } else {
                        this.lotteryList = []
                    }
                }
            })
        },
// 删除
onDelete(index) {
           if (this.lotteryList[index].hl_id) {
               // 真实数据
               console.log('真实数据: ');
               delLottery({
                   hl_id: this.lotteryList[index].hl_id
               }).then(res => {
                   if (res.state == 0) {
                       this.$message({
                           message: '删除成功',
                           type: 'success'
                       });
                       this.getList()
                   }
               })
           } else {
               // dom数据
               console.log('dom数据: ');
               this.lotteryList.splice(index, 1);
           }
       },
watch: {
        // lotteryList: {
        // 不要监听列表用的lotteryList数据 因为最终要修改lotteryList数据 会造成监听无限执行
        watchLotteryList: {
            // 深度监听会造成val和oldVal的值相同
            handler(val, oldVal) {
                setTimeout(() => {
                    console.log('---', this.curIndex, this.lotteryList[this.curIndex])
                    // 存在id 即编辑状态下
                    if (this.curIndex !=null && this.lotteryList[this.curIndex].hl_id) {
                            console.log('originLotteryList: ', this.originLotteryList[this.curIndex]);
                            console.log('val: ', val[this.curIndex]);
                            if (this.isEqual(this.originLotteryList[this.curIndex], val[this.curIndex])) {
                                console.log('2个对象数据一致')
                                this.lotteryList[this.curIndex].isEdit = false
                                // 原始数据也要同步修改
                                this.originLotteryList[this.curIndex].isEdit = false
                            } else {
                                console.log('2个对象数据不一致!!!')
                                this.lotteryList[this.curIndex].isEdit = true
                                this.originLotteryList[this.curIndex].isEdit = true
                            }
                            console.log('最后', this.lotteryList[this.curIndex])
                            // this.curIndex = null
                    }
                }, 50)
            },
            deep: true
        },
    },
// 记录当前选中的数据 select则用@change事件 其他元素添加@click事件
        onItem(index) {
            console.log('选中下标', index)
            this.curIndex = index
        },
// 对比2个对象是否一致
        isEqual(objA, objB){
            //相等
            if(objA === objB) return objA !== 0 || 1/objA === 1/objB;
            //空判断
            if(objA == null || objB == null) return objA === objB;
            //类型判断
            if(Object.prototype.toString.call(objA) !== Object.prototype.toString.call(objB)) return false;

            switch(Object.prototype.toString.call(objA)){
                case '[object RegExp]':
                case '[object String]':
                    //字符串转换比较
                    return '' + objA ==='' + objB;
                case '[object Number]':
                    //数字转换比较,判断是否为NaN
                    if(+objA !== +objA){
                        return +objB !== +objB;
                    }

                    return +objA === 0?1/ +objA === 1/objB : +objA === +objB;
                case '[object Date]':
                case '[object Boolean]':
                    return +objA === +objB;
                case '[object Array]':
                    //判断数组
                    for(let i = 0; i < objA.length; i++){
                        if (!this.isEqual(objA[i],objB[i])) return false;
                    }
                    return true;
                case '[object Object]':
                    //判断对象
                    let keys = Object.keys(objA);
                    for(let i = 0; i < keys.length; i++){
                        if (!this.isEqual(objA[keys[i]],objB[keys[i]])) return false;
                    }

                    keys = Object.keys(objB);
                    for(let i = 0; i < keys.length; i++){
                        if (!this.isEqual(objA[keys[i]],objB[keys[i]])) return false;
                    }

                    return true;
                default :
                    return false;
            }
        },
// 防抖函数
        debounce(func, wait = 300, timer, immediate = false) {
            //  移除定时器
            if (timer !== null) {
                clearTimeout(timer)
            }
            //  是否立即执行
            if (immediate) {
                //  立即执行
                const callNow = !timer
                timer = setTimeout(() => {
                    timer = null
                }, wait)
                if (callNow) typeof func === 'function' && func()
            } else {
                //  设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
                timer = setTimeout(() => {
                typeof func === 'function' && func()
                }, wait)
            }
        },
上一篇下一篇

猜你喜欢

热点阅读