每月进步一点点--202311

816 阅读10分钟

17. 三个代码优化点

  • window对象,书写的时候可以省掉window.索引

正常:

  const shareChannels = getQueryString(window.location.search, 'shareChannels');

优化:

    const shareChannels = getQueryString(location.search, 'shareChannels');
  • 只会在一个地方使用的常量,不必提取到公共常量文件

反例: 把只会在一个地方使用的常量,提取到src/common/constants.ts中,这段代码,放到使用的业务文件里面就行了,阅读与查找起来更方便

export const taskContentMap: TLooseStrObj = {
  '090101':
    '首次“一对一专属理财经理”自我介绍;告知客户服务升级(贵宾客户专属产品及服务权益体系升级亮点);邀请添加客户企业微信;邀约与客户首次面访时间',
  '090102': '新增邀约',
   // ...
};
  • 可以优化的if判断语句

正常:

    const launchBtn = document.getElementById('launch-btn');
    if(launchBtn){
      launchBtn.removeEventListener('launch', handleLaunch);
    }
   

优化:

    const launchBtn = document.getElementById('launch-btn');
    launchBtn?.removeEventListener('launch', handleLaunch);

16. IOS13的一个兼容性问题

IOS13手机操作系统,如果H5应用的域名使用的是https协议, 在网站中,以Ajax的方式,请求一张同域名但协议却是http图片文件数据,是获取不到图片的二进制数据的,需要修改成https协议才可以,而在Android上没有这个问题,而且不是所有的IOS系统都是如此,高版本的也没有这个问题。

15. 一个中文占几个字节?

ASCII 字符集总共规定了128种字符规范,但是并没有涵盖西文字母之外的字符,当需要计算机显示存储中文的时候,就需要一种对中文进行编码的字符集,国家标准委员会对中文制定了3种编码规则 GB2312,GBK和GB-18030。GB2312只涵盖了6000 多个汉字,还有很多没有包含在其中,所以出现了GBK和GB-18030,GBK是双字节编码,每个字符用两个字节表示。GB18030是多字节字符集,它的字符可以用一个、两个或四个字节表示。码位空间由各字节的范围确定。Unicode 在一个字符集中包含了世界上所有文字和符号,统一编码,来终结不同编码产生乱码的问题。Unicode 是一个符号集, 它只规定了每个符号的二进制值,但是符号具体如何存储它并没有规定,前面提到, Unicode 字符集的编码范围是 0x0000 - 0x10FFFF,因此需要 1 到 3 个字节来表示。

  • ASCII 码中,一个英文字母(不分大小写)为一个字节,ASCII码只能表示英文字母、数字、标点符号等基本字符。
  • UTF-8 编码中,采用变长存储文字和符号。 少数是汉字每个占用3个字节,多数占用4个字节。UTF-8 的编码规则如下(U+ 后面的数字代表 Unicode 字符代码):
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
  • UTF-16 编码中,通常汉字占2个字节,CJKV扩展B区、扩展C区、扩展D区中的汉字占4个字节(一般字符的Unicode范围是U+0000至U+FFFF),而这些扩展部分的范围大于U+20000,因而要用两个UTF-16)
  • UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。
  • Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
  • 符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 . 占1个字节的大小,中文句号 。占2个字节的大小。

14. pre和p标签的区别

pre默认支持\n转义换行符,但内容超出不能自动换行,需要添加如下的设置,才能换行。p标签默认自动换行,可是对\n不识别,所以要处理富文本的内容展示,还得用pre标签

pre {
  white-space: pre-wrap;
  word-wrap: break-word;
}

13. 发现postcss-plugin-px2rem插件一个bug

如下一段代码,经过postcss-plugin-px2rem插件转换后,上下两部分的字体大小既然一样,是不是很诡异。

  .cardWrap {
    .infoWrap {
      // ...
      .left {
        .infoValue {
          // ...
          font-size: 18px;  
        }
      }
      
      .common {
        // ...
        .commonItem {
          // ...
          .infoValue {
            font-size: 14px;
          }
       }
   }  
 }

image.png

image.png

而本地调试的时候,发现没问题。看了一下package.json中postcss-plugin-px2rem版本的写法,瞬间明白了。Dev-Ops CI工具构建工具,每次构建时,会重新安装postcss-plugin-px2rem,如下的这种写法,即便是存在yarn.lock文件,也会对postcss-plugin-px2rem进行升级,而postcss-plugin-px2rem最新的版本肯定有问题,本地安装一次之后,就不会再安装了。所以本地工作正常。

{
  "postcss-plugin-px2rem": "^0.8.1",
 }

12. 今天发现coding代码平台的一个大坑,在线解决冲突的话,会把公共分支的内容,合并到自己的特性分支

比如说你要把自己的特性分支feature/20231116-功能说明-姓名拼写合并到release/20231116, 合并代码的时候出现了冲突,你在coding网站在线解决冲突而非本地命令行,会把release/20231116的功能同步到自己的特性分支feature/20231116-功能说明-姓名拼写,造成潜在的发版隐患。

11. 分享一个便捷生成各种尺寸测试图片的网站

点击这里跳转到dummyimage.com,这个网站支持生成各种尺寸的测试图片,图片的格式支持jpg|gif|png, 支持自定义图片的背景色,文字颜色,图片上的文字,是个很好的测试工具、

image.png

10. 判断语句,需要优化的一个点。可以一次性判断的结果,就无需每次都去判断。

instance.interceptors.response.use(
  function (response) {
    const { headers, status, statusText, data, config } = response;
    if (status === 200) {
       // 不好的写法
       if (location.href.includes('needEncrypt')) {
          // ...
       }
    } 
  }
);
// 好的做法
const isNeedEncrypt=location.href.includes('needEncrypt');
instance.interceptors.response.use(
  function (response) {
    const { headers, status, statusText, data, config } = response;
    if (status === 200) {
       if (isNeedEncrypt) {
          // ...
       }
    } 
  }
);

9. 使用浏览器浏览网页时,为什么不建议同时打开很多标签页?

如下图所示,每打开一个网页,都会占用一定的内存,而操作系统分配给浏览器的内存不是无限制的,所以不要打开过多的浏览器标签页,因为那样会造成浏览器运行缓慢或崩溃。

image.png

8. 在电脑端emoji表情展示正常,在手机端有些emoji表情展示不出来,如下图所示,是什么原因?

image.png image.png

emoji 也是Unicode字符。2010年,Unicode 开始为 Emoji 分配码点。比如:U+1F4C5,U+1F468, U+1F600等。 Unicode 只是规定了 Emoji 的码点和含义,并没有规定它的样式。举例来说,码点U+1F600表示一张微笑的脸,但是这张微笑的脸表情长什么样,则由各个系统自己实现。如果用户的系统没有实现这个Emoji符号,用户就会看到一个没有内容的方框,因为系统无法渲染这个码点。所以在PC端展示正常的emoji表情,在Android或IOS系统上,可能展示不太正常,解决方案是:

  • 下载响应操作系统的emoji字体,然后用css自定义一个字体类型,进行加载显示
  • 用图片代替emoji表情
  • 升级手机操作系统

7. 手机和电脑连接同一个WiFi,手机无法访问电脑上的IP地址网页,该如何解决?

如果你的系统没有windows防火墙功能,而许多网上的文章都说要开启防火墙功能,沿着这条思路走,就是一条死胡同。正确的解决方法是,让电脑共享出一个移动WiFi热点,用手机去连接电脑上的这个WiFi热点,然后启动电脑端的单页应用项目时,会显示本机的IP地址,在手机上用这个地址去访问电脑上的网页,你会发现,是可以访问的。

6. 在vue3 hook中使用vue-router需要注意一个细节,给route赋值的时候,有可能router还没初始化,造成运行时报错。

import { useDefaultLink } from '@shared/hooks';
import { useGlobalStore } from '@shared/store';
import { useRoute } from 'vue-router';
const route = useRoute();
export const useToArticleDetail = () => {
  const { toPath } = useDefaultLink();
  const globalStore = useGlobalStore();
      const _query = {
      objId: newsId,
      // 会报错TypeError: Cannot read properties of undefined (reading 'query')
      unionId:route.query.unionId,
    };
}

正确的解决思路是用别的工具,解析url上的查询参数

import { getQueryString } from '@shared/utils';
const unionId = getQueryString('unionId') || '';

5. 容易产生bug的一段代码

下面这段代码中的这一句operationType.value = retdata.operationType || '';,在特定场景下,会产生缺陷。就是retdata.operationType等于0的时候,0是个有效值,但operationType.value最终会把赋值为'',造成下一个接口提交数据报错。

    let res;
    if (isEdit.value) {
      res = await videoApi.updateVideo(data);
    } else {
      res = await videoApi.createVideo(data);
    }

    const { ret, retdata = {} } = res;
    const { auditOperation, commitBy = '' } = retdata;

    operationType.value = retdata.operationType || '';
    console.log({ operationType: operationType.value });

4. 后端接口返回的文本中有换行符,业务要求,换行要正常显示,正确的做法是?

刚开始试了一下v-html, 发现没有任何效果, 正确的做法是使用pre标签,但要注意一些细节问题,浏览器会对pre标签设置一些默认样式,要对默认的字体,行高进行重置,才是正常的效果。

3. 业务场景复杂的展示效果调试技巧

要产生某一些业务数据,操作流程和需要满足的业务条件很多,如果想看某种场景下的展示效果,直接写死一些假数据,调整页面布局。无需按照常规思维,按步骤操作,那样太浪费时间了。

2. 如果要测试一个交互场景问题,要填写许多表单项之后,才能触达这种交互场景,有没有省力省时的调试技巧?

这里分享一种思维,我遇到的具体问题肯定和大家不一样,就是对要测试的交互场景进行抽象,找出关键部分,用最少的资源条件,进行交互场景的模拟。完整的从头到尾填写许多表单数据之后,测试交互问题的常规思路不足取。

1. Antd Menu组件, 通过react-router跳转页面,管理后台左侧响应的菜单不高亮,如何修复?

解决思路:从当前页面url获取到路由路径,根据路由路径从左侧导航菜单列表中,找到Menu组件要设置打开的父级菜单和当前页面的id, 进行设置即可。setCurrent用于设置高亮的菜单项,setOpenKeys用于设置高亮的菜单项父级菜单处于展开状态。另外还发现,管理后台左侧的导航菜单与路由不是一一对应的,有些路由比如说编辑类页面路由,是无需设置高亮的。

import React, { useState, useEffect } from 'react';
import { Menu } from 'antd';
import { useLocation, Link } from 'react-router-dom';
const MenuList = () => {
  const location = useLocation();
  const [, rootPath] = location.pathname.split('/');
  const [current, setCurrent] = useState(rootPath);
  const [openKeys, setOpenKeys] = useState();
  const { menu = [] } = useSelector((state) => state.base);
  

  if(current !== rootPath) {
    setCurrent(rootPath);
    menu.some((item) => {
      return item.resources.some((subItem) => {
        if (subItem.resShortCode === rootPath) {
         // 注意这里必须转换成字符串
          setOpenKeys(`${item.resId}`);
        }
        return subItem.resShortCode === rootPath;
      });
    });
  }
  
 return( 
  <Menu
     theme="dark"
     mode="inline"
     selectedKeys={[current]}
     openKeys={[openKeys]}
 >)
}