开发随笔(前端内容)

 写在前面,博主是个在北京打拼的码农,从事前端工作5年了,做过十多个大大小小不同类型的项目,最近心血来潮在这儿写点东西,欢迎大家多多指教。

  • 对于文章中出现的任何错误请大家批评指出,一定及时修改。
  • 有任何想要讨论和学习的问题可联系我:13287946835@139.com。
  • 发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。

目录

关于日常开发中遇到的那些~~~

一、划过显示二维码

二、关于打包时候为什么要分包的个人理解

三、git命令合并分支代码

四、翻转对象的方法

使用 Object.fromEntries 将数组转成对象

Object.fromEntries() 方法把键值对列表转换为一个对象

五、项目性能优化

1、开启gzip压缩代码

2、分包

六、关于 BuildAdmin使用中的问题

七、前端请求接口excel文件并下载

八、报错‘v-html‘ directive can lead to XSS attack


关于日常开发中遇到的那些~~~

本文关键字:字符串键返回自动变成了数字

一、划过显示二维码

     <span v-if="!!addMessage.qrCode" style="position: relative;"><img width="32px" height="32px" @mouseover="$event.currentTarget.src = mouseoverPng,showBigQrCode=true" @mouseout="$event.currentTarget.src = mouseoutPng,showBigQrCode=false" :src="mouseoutPng" alt="二维码"> <img v-show="showBigQrCode" width="220px" height="220px" style="position: absolute;left:50px" :src="addMessage.qrCode" alt="二维码"></span>

二、关于打包时候为什么要分包的个人理解

我们打包的文件每次更新其中的代码,打包后的文件识别到代码更新会修改相关文件的hash值,来进行热更新等,而我们如果把所有代码打包成一个文件,那么当我们只是修改了一行代码,整个文件都会重新加载,分包后只需要更新那行代码所在的文件就行了,所以分包后应用性能上有了提升

三、git命令合并分支代码

原文

四、翻转对象的方法

我们都知道数组翻转方法reverse();那么怎么翻转对象呢

使用 Object.fromEntries 将数组转成对象

Object.fromEntries() 方法把键值对列表转换为一个对象

var obj={'1键':1,'2键':1};

const arr=Object.entries(obj);//转成数组[{'1键',1},{'2键',1}]

//翻转

const reverseArr = arr.reverse();

var finallyObj=Object.fromEntries(reverseArr);

注意注意,如果你的键是数字,某些浏览器会自动排序(相关文章),应该让后端把键转成字符串避免排序出错问题,否则每次都得前端做数据处理;

因为前端如果使用reverseArr.map(item=>[item[0]+'',item[1]],你会发现确实键都变成了字符串,但你使用Object.fromEntries(reverseArr.map(item=>[item[0]+'',item[1]])时会发现键又变成了数字

如果全数字组成的字符串不行,就应该这样就可以Object.fromEntries(reverseArr.map(item=>[item[0]+'随意字母',item[1]])

再给大家提供一个合并对象方法

console.log('{...{1:1,2:2},3:3} :>> ', {...{1:1,2:2},3:3});

五、项目性能优化

1、开启gzip压缩代码

spa这种单页应用,首屏由于一次性加载所有资源,所有首屏加载速度很慢。解决这个问题非常有效的手段之一就是前后端开启gizp(其他还有缓存、路由懒加载等等)。gizp其实就是帮我们减少文件体积,能压缩到30%左右,即100k的文件gizp后大约只有30k。

vue-cli初始化的项目中,是默认有此配置的,只需要开启即可

2、分包

不分包:

每次都得重新下载更新后的文件

首屏的渲染速度变慢;

当搭建的应用注重用户打开速度时,合理的分包策略有助于减少用户首屏加载应用时加载的资源数量,并且对于部分资源可以复用,避免重复加载,从而提升用户体验。

拆出了common公共库,这个库主要是node_modules中的公共库,更新频率低,其它页面chunk都可以公用这块库,因此其它页面都只包含自己业务代码

  • 对于一些不需要立即使用的组件,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js;

  • 这些chunk.js会在需要时从服务器加载下来,并且运行代码,显示对应的内容;

app.js文件中,是我们自己编写的所有代码逻辑。

chunk-vendors.js中是第三方的包(vuejs,vue-router,axios) 。

简单来说分包就是在webpack配置中,对entry入口配置多增加一些入口文件,然后配置output出口文件为动态名字,之后通过webpack的plugin把公共的代码chunk块都提取识别出来(可以通过hash名称捕获到具体文件),放入一个公共的bundle包文件里,就可以实现分包

六、关于 BuildAdmin使用中的问题

当我们使用table组件时传入要渲染的内容

<Row class="margin-top-10 searchable-table-con1">
                <Table :columns="userColumn" :data="userList"></Table>
                <Spin size="large" fix v-if="loadings"></Spin>
            </Row>

userColumn: [
                    {
                        title: '用户ID',
                        key: 'id',
                        width: 100,
                        align:'center',
                        fixed:'left'
                    },
                    {
                        title: '账号/手机号',
                        key: 'username',
                        width: 300,
                        align:'center',
                        render: (h, params) => {
                           
                            return h('span',this.$comJs.getTel(params.row.username));
                           
                        }
                    },
                    {
                        title: '声音锁',
                        key: 'isSoundLock',
                        width: 100,
                        align:'center',
                        render: (h, params) => {
                            if(params.row.isSoundLock == 1){
                                return h('span','已开启');
                            }else{
                                return h('span','未开启');
                            }
                        }
                    },
                    {
                        title: '小鹅通',
                        key: 'isXiaoeTong',
                        width: 100,
                        align:'center',
                        render: (h, params) => {
                            if(params.row.xiaoeTechId){
                                return h('span','已同步');
                            }else{
                                return h('span','未同步');
                            }
                        }
                    },
                    {
                        title: '姓名',
                        key: 'name',
                        width: 100,
                        align:'center'
                    },
                    {
                        title: '账户类型',
                        key: 'orgTypeName',
                        width: 100,
                        align:'center'
                    },
                    {
                        title: '会员类型',
                        key: 'flag',
                        width: 100,
                        align:'center',
                        render: (h, params) => {
                            if(params.row.flag==0){
                                return h('span','普通会员');
                            }else if(params.row.flag==1){
                                return h('span','svip会员');
                            }else{
                                return h('span','vip会员');
                            }
                        }
                       
                    },
                    {
                        title: '推荐数据',
                        key: 'total',
                        width: 100,
                        align:'center',
                        render: (h, params) => {
                            return h('div', [
                             h('span', {
                               props: {
                                         type: 'primary',
                                         size: 'small'
                                     },
                                     style: {
                                         color: '#3478f6',
                                         cursor:'pointer'
                                     },
                                    on: {
                                    click: () => {
                                        if(params.row.total){
                                            this.openTotal(params.row);
                                        }else{
                                            this.$Message.success('该用户暂无推荐数据!')
                                        }
                                    }
                                },
                            }, (params.row.total))
                            ])
                        }
                    },
                    {
                        title: '用户类型',
                        key: 'regType',
                        width: 100,
                        align:'center',
                       render: (h, params) => {
                        if(params.row.regType==2){
                            return h('span','游客用户');
                           
                        }else{
                            return h('span','普通用户');
                        }
                       }
                    },
                    {
                        title: '单位',
                        key: 'orgInfo',
                        width: 100,
                        align:'center'
                    },
                    {
                        title: '行业',
                        key: 'industryName',
                        width: 100,
                        align:'center'
                    },
                    {
                        title:'地区',
                        key:'operDtails',
                        width: 100,
                        align:'center'
                    },
                    {
                        title:'所属渠道商',
                        key:'distributorName',
                        width: 100,
                        align:'center',
                    },
                    {
                       title: '注册时间',
                        key: 'cTime',
                        width: 200,
                        align:'center'
                    },
                    {
                       title: '最后登录时间',
                        key: 'loginTime',
                        width: 200,
                        align:'center'
                    },
                    {
                        title: '操作',
                        key: 'action',
                        width: 620,
                        align: 'center',
                        fixed:'right',
                        render: (h, params) => {
                            return h('div', [
                            h('Button', {
                                    props: {
                                        // type: params.row.loginSource==3?'ghost':'primary',
                                        type:'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                            // if(params.row.isPushTo==0){
                                                 this.SYPUSH(params.row)
                                            // }else if(params.row.isPushTo==1) {
                                                // this.SYPUSH(params.row)
                                            // }
                                        }
                                    }
                            },(this.$comJs.getPermissions('USER_M_UPGRADE')?((params.row.loginSource==3)?'已推送声誉系统':'推送声誉系统'):'')) ,
                            h('Button', {
                                    props: {
                                        type: params.row.isPushTo==0?'primary':'ghost',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                            if(params.row.isPushTo==0){
                                                 this.DataSide(params.row)
                                            }else if(params.row.isPushTo==1) {
                                                this.DataSide(params.row)
                                            }
                                        }
                                    }
                                },(this.$comJs.getPermissions('USER_M_UPGRADE')?((params.row.isPushTo==0)?'添加数据终端':'已添加数据终端'):'')) ,
                            h('Button', {
                                    props: {
                                        type: params.row.isTable==0?'primary':'ghost',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                            if(params.row.isTable==0){
                                                 this.Upgrade(params.row)
                                            }
                                        }
                                    }
                                },(this.$comJs.getPermissions('USER_M_UPGRADE')?((params.row.gId==0)?'添加舆情服务':'已添加舆情服务'):'')) ,
                             h('Button', {
                               props: {
                                         type: 'primary',
                                         size: 'small'
                                     },
                                     style: {
                                         marginRight: '5px'
                                     },
                                    on: {
                                    click: () => {
                                         this.sysUserInfor(params.row.id,params.row.username);
                                    }
                                },
                            }, (this.sessionStrong.getPersession().indexOf('USER_AUTH_E')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1)?'用户详情':''),
                             h('Button', {
                                    props: {
                                        type: params.row.isFollow==0?'primary':'ghost',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                             this.follow(params.row,params.index)
                                        }
                                    }
                                }, (params.row.isFollow==0)?'关注':'取消关注'),
                                h('Button', {
                                    props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                             this.href(params.index)
                                        }
                                    }
                                }, (this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1)?'查看监测方案':''),
                                h('Button', {
                                    props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                             this.joinblack(params.row)
                                        }
                                    }
                                }, (this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1)?'加入黑名单':""),
                                    ((!params.row.isAuthCom|| !params.row.isAuthPerson)&&(this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1))?h('Button', {
                                         props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px',
                                        marginTop: '5px',
                                    },
                                    // 按钮是否显示,请返回布尔值
     
                                      on: {
                                          click: () => {
                                            this.nowEditItemId=params.row.id;
                                            this.$refs.person.valueObj={};
                                            this.$refs.firm.valueObj={};
                                            this.$refs.person.searchOverList=[];
                                            this.$refs.firm.searchOverList=[];
                                            this.childCompanyName='';
                                            if(!params.row.isAuthPerson){
                                                this.openPopup=true;

                                            }else{
                                                this.openFirmPopup =true;
                                            }
                                          }
                                      },
                                     
                                  }, ((!params.row.isAuthCom|| !params.row.isAuthPerson)&&(this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1))?'添加声誉服务':''):'',
                            ]);
                        }
                     }
                ],

当我们要渲染操作按钮

操作按钮中我们使用了vue的h自定义渲染内容函数

可有的时候我们要判断是否显示该渲染内容,针对h函数我们要怎么去控制显示隐藏,我在这里是使用三元判断运算符

(this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1)?'加入黑名单':""),
                                    ((!params.row.isAuthCom|| !params.row.isAuthPerson)&&(this.sessionStrong.getPersession().indexOf('USER_M_P')!=-1||this.sessionStrong.getPersession().indexOf('ADMIN')!=-1))?h('Button', {
                                         props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px',
                                        marginTop: '5px',
                                    },
                                    // 按钮是否显示,请返回布尔值
     
                                      on: {
                                          click: () => {
                                            this.nowEditItemId=params.row.id;
                                            this.$refs.person.valueObj={};
                                            this.$refs.firm.valueObj={};
                                            this.$refs.person.searchOverList=[];
                                            this.$refs.firm.searchOverList=[];
                                            this.childCompanyName='';
                                            if(!params.row.isAuthPerson){
                                                this.openPopup=true;

                                            }else{
                                                this.openFirmPopup =true;
                                            }
                                          }
                                      },
                                     
                                  }, '添加声誉服务'):'',

七、前端请求接口excel文件并下载

核心是通过a标签去触发blob文件下载,用的是a标签的download方法


    batchExport() {
      if (!this.checkedIds.length) return this.$message.warning("请勾选数据");
      this.$http({
        method: "GET",
        url: "/cbrc/user_center/department/export",
        responseType: "blob",
        params: {
          ids: this.checkedIds.join(","),
        },
      }).then((res) => {
        if (res) {
          this.downloadFile(res);
        }
      });
    },
    downloadFile(res) {
      let url = window.URL.createObjectURL(
        new Blob([res.data], { type: res.headers["content-type"] })
      );
      let a = document.createElement("a");
      a.style.display = "none";
      a.href = url;
      a.setAttribute("download", `导出数据.xls`);
      document.body.appendChild(a);
      a.click();
      url = window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    },

八、报错‘v-html‘ directive can lead to XSS attack

让我们来解决这个问题

过滤 XSS警告

(vue3)因为后台给的是一些标签图片与换行符等必须要使用v-html,但触发了eslint的xss安全警告

 <!-- eslint-disable vue/no-v-html -->
            <div class="special-situation-detail-content" v-html="simpleText"></div>

解决方法:创建节点后把后台给的simpleText赋值给节点的innerHTML,然后把元素插入父节点 special-situation-detail-content,就不需要用v-html了,当然你如果非要用,就得把eslint的某些配置改一下了,这个我就不去调查了。

 const elementCreate = document.createElement('div');
                        elementCreate.innerHTML = data.item.contentHtml;
                        data.simpleText = elementCreate.innerHTML;
                        console.log(data.simpleText);

                        nextTick(() => {
                            console.log(document.querySelector('.special-situation-detail-content'));
                            document.querySelector('.special-situation-detail-content')?.appendChild(elementCreate);
                        });

补充:各位可以不用nextTick方法,我没在mounted中获取DOM节点所以没拿到只能用nextTick

 文章传送门:大屏开发教学 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JianZhen✓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值