28. Browserslist: caniuse-lite is outdated. Please run xxx 解决方案?
运行下面的命令更新有些缓慢,推荐下面的操作:
npx browserslist@latest --update-db
先删除这两个依赖包
yarn remove caniuse-lite browserslist
再安装最新的依赖包即可
yarn add -D caniuse-lite browserslist
27. 为什么console.log打印对象时,打印的是最终结果,而不是实时值?
如下所示:
//执行以下代码
let obj={name:'张三'};
console.log(obj);
obj.name='李四';
console.log打印一个对象时,打印对象指向的是一片内存地址。
- 不展开对象看时,
console.log()是按照代码执行顺序,同步地输出了对象当时的快照。 - 展开对象时,它其实是重新去内存中读取对象的属性值,此时对象属性已被更改,所以展开对象后,看到的不是console.log输出行那一刻的值了。
26. 正则表达式的test方法多次执行运行结果有误,是什么原因?
let reg = /[\u4e00-\u9fa5]+/g;
console.log(reg.test('中文')) // true
console.log(reg.test('中文')) // false
console.log(reg.test('中文')) // true
console.log(reg.test('中文')) // false
console.log(reg.test('中文')) // true
是因为正则表达式中的 g ,循环匹配的问题。正则的 lastIndex 从字面上来讲就是最后一个索引,实际上它的意思是正则表达式开始下一次查找的索引位置,第一次的时候总是为 0 的,第一次查找完了的时候会把 lastIndex 的值设为匹配到得字符串的最后一个字符的索引位置加 1,第二次查找的时候会从 lastIndex 这个位置开始,后面的以此类推。如果没有找到,则会把 lastIndex 重置为 0。要注意的是,lastIndex 属性只有在有全局标志正则表达式中才有作用。
解决方法:
-
- 重置 lastIndex
reg.lastIndex = 0
- 重置 lastIndex
-
- 重新编译正则
reg.compile()
- 重新编译正则
25. 企业微信H5应用,详情页面,vConsole老是报图片加载错误,然而并没发现页面上有图片展示异常,是什么原因?
最后查明,是avatar的初始值为空,误触发了浏览器请求图片资源,得到了一个404响应,造成控制台输出404错误。而在PC端却不会,猜测可能是PC端请求响应速度快,很快就给avatar填充了一个有效值。
<img class="avatar" :src="avatar" />
解决方法就是加一个判断条件,当avatar为空时,不让浏览器发资源请求,注意这里不能使用v-show,使用v-show照样会报错,只能用v-if.
<img v-if="avatar" class="avatar" :src="avatar" />
24. wx.previewFile有兼容性问题,在IOS低版本手机上有时会报文件下载失败,导致无法预览文件内容。该怎么办?
这里提供一个思路,可以把文件内容转换成多幅图片,然后用图片预览组件,展示文件内容。
<!-- 弹窗协议-->
<ActionSheet v-model:show="maskShow" :round="false">
<div class="mask-content">
<img
v-for="(item, index) in protocolInfo?.relationList[listIndex]?.convertImgUrl?.split(',')"
:src="item"
:key="index"
@click="onImgClick(index, protocolInfo)"
/>
</div>
<button @click="maskShow = false" class="mask-btn" :style="{ background: protocolInfo.color }">返回</button>
</ActionSheet>
import { ImagePreview , ActionSheet } from 'vant';
import { ref,reactive } from 'vue';
const protocolInfo=reactive({
title: '',
relationList: [],
}),
const maskShow = ref(false);
const listIndex = ref(0); //选中哪个协议
// 微信端点击图片进行预览
const onImgClick = (index: number, protocolInfo: any) => {
ImagePreview({
images: protocolInfo?.relationList[listIndex.value]?.convertImgUrl?.split(','),
loop: false, // 关闭循环播放
startPosition: index || 0,
});
};
23. 如何用css实现一个跑马灯效果?
跑马灯代码 参见这里,实现思路,定义一个从左到右,无限循环移动的动画。在文字的样式上添加这个动画。文字的宽度要和文字容器的宽度一样,把文字重复两遍,才能实现左移无缝衔接效果,不会第一次移动结束后,出现无文字移动的空白时间。
22. 上传到服务器的pdf文档,下载下来打开内容有乱码,是什么原因?
可能的原因是:
- 字体不匹配:如果PDF文件中的字体和当前系统中的字体不匹配,就会导致中文乱码。
解决方法:在读取或者写入PDF文件时,需要指定正确的字体,确保字体匹配。
- 编码不正确:PDF文件中的中文字符使用的编码格式与当前系统的设置不一样,也会导致中文乱码。
解决方法:在读取或者写入PDF文件时,需要指定正确的编码格式,确保对中文字符进行正确的编码和解码。
21. 把一个get请求url直接输入到浏览器地址栏,看到的响应是正常的,而通过本地vite proxy转发,收到的状态码是200,然而响应体什么也没有,该如何定位问题出在哪里?
查看一下,vite server的proxy说明,vite server的proxy 使用的是 node http-proxy插件,http-proxy插件有许多事件,可供调试使用。要看响应体,用到的proxy事件是proxyRes,不过得到的是二进制数据,直接在控制台用console.log打印的话,完全不可辨识。需要把二进制数据转换成字符串类型打印,才能看清楚内容。
'/wxwork/virtual/': {
target: env.VITE_API_HOST,
changeOrigin: true,
secure: false,
configure: (proxy, _options) => {
// 转发出错
proxy.on('error', (err, _req, _res) => {
console.log('proxy error', err);
});
// 拦截请求事件
proxy.on('proxyReq', (proxyReq, req, _res) => {
console.log('Sending Request to the Target:', req.method, req.url);
});
// 拦截响应
proxy.on('proxyRes', (proxyRes, req, _res) => {
console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
const bodyStr = await getBody(proxyRes);
const bodyObj = JSON.parse(bodyStr);
// 字符串打印美化
console.log(JSON.stringify(bodyObj, null, 2));
});
},
}
// 将二进制数据转换成字符串
function getBody(proxyRes) {
return new Promise<string>((resolve, reject) => {
let body: any = [];
let bodyStr = '';
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', function () {
bodyStr = Buffer.concat(body).toString();
// console.log('getBody ======', bodyStr);
resolve(bodyStr);
});
});
}
20. 如果误将ant-design-vue的upload组件的file-list属性设置为空数组,会发生什么异常?
今天踩到一个坑了, 误将file-list属性设置为空数组,如下所示, 然后发现handleChange函数,始终无法获取上传文件到服务器,服务器返回的响应值。通过排查,才发现是file-list属性值设置有误造成的。
<a-upload
:file-list="[]"
name="avatar"
list-type="picture-card"
class="avatar-uploader"
:show-upload-list="false"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
:before-upload="beforeUpload"
@change="handleChange"
>
19. 将图片下载到项目中,用作文件上传组件的默认图片,如何解决默认图片地址为本地地址,上传到文件服务器后,再次进入编辑页面,调用查询详情接口,返回一个本地地址,造成资源加载报错的问题?
// 导入的本地图片
import defaultAgreementBgPic from '@feature-manage/assets/images/agreement/agreement-default-bg.png';
在编辑页面,详情查询接口数据解析数据逻辑中,添加这样的判断条件,就能很好地解决页面加载本地资源报错问题。
agreementForm.backgroundImg = backgroundImg.includes('@fs')
? defaultAgreementBgPic
: backgroundImg;
18. 对于一些第三方UI库,样式类名形如 class="_listItem_11978",用js动态创建出来的样式类型,如何进行选中并修改样式?
答案是用属性选择器,匹配以_listItem开头的样式类名
:deep(div[class^='_listItem']) {
margin-bottom: 0;
}
顺带复习一下这一块的知识点:
[attr]表示带有以 attr 命名的属性的元素。[attr=value]表示带有以 attr 命名的属性,且属性值为 value 的元素。[attr~=value]表示带有以 attr 命名的属性的元素,并且该属性是一个以空格作为分隔的值列表,其中至少有一个值为 value。[attr|=value]表示带有以 attr 命名的属性的元素,属性值为“value”或是以“value-”为前缀(-为连字符,Unicode 编码为 U+002D)开头。典型的应用场景是用来匹配语言简写代码(如 zh-CN、zh-TW 可以用 zh 作为 value)。[attr^=value]表示带有以 attr 命名的属性,且属性值是以 value 开头的元素。[attr$=value]表示带有以 attr 命名的属性,且属性值是以 value 结尾的元素。[attr*=value]表示带有以 attr 命名的属性,且属性值至少包含一个 value 值的元素。
17. 今天又遇到另一种情况的404问题, 有一个接口,在浏览器开发调试网络窗口下,报404,而地址看着好像也没问题,是什么原因?
原来是本地代理服务转发配置引起的问题, 本地代理转发服务匹配一定的路径前缀,匹配上了就行对接口进行代理,而那个接口缺少对应的接口前缀,所以本地代理服务未对这个接口进行转发。且这个接口比较特别,只有它一个,需要另外写一条路径匹配规则。对于看着没有任何问题的接口,如果报404,八成是代理转发配置出了问题。
16. 今天碰到一桩怪事, 在url地址栏输入一个接口地址,报下面的错,启动一个本地服务,打开页面操作,调用相同的接口时却报404, 你说接口不存在吧,在浏览器地址栏输入,却有反应。你说接口地址存在吧,在页面中调用却报404,这是什么原因?
{
"ret": 1000001,
"traceId": "f8b9dceee402a3cd",
"retmsg": "请重新登录"
}
后面查明, 只要接口符合一定的前缀,在浏览器地址栏输入,未登录都会返回请重新登陆。哪怕再满足前缀特征的条件下,后面的接口地址乱输一气,在浏览器地址栏也有反应。推测是后端服务,对于满足一定路径前缀的接口,接口不存在的时候且未登录的情况下,都返回请重新登录。所以不能根据url返回这一段,就说这个接口真的存在。
15. 运行nx run portal:build --mode sit 命令, 控制台报错 permission denied, open 'D:/local-fe-webapp/dist/sit/portal/latest/assets/swiper-slide.0fb239bc.js, 造成构建部署包失败,是什么原因?
是因为同时开了两个bash终端,一个正在运行项目,另一个终端正在打包,正在打包的终端会清除dist/sit目录下的所有内容,而正在运行项目的终端,还在使用dist/sit/portal/latest/assets/swiper-slide.0fb239bc.js下的文件,造成构建删除原有包报错,异常退出。造成打包失败。解决方法,关闭正在运行项目的终端, 然后手动删除dist/sit文件下的所有内容,如果删除报错,就把vscode关掉,再去删除。然后重新构建,就能成功打包。
14. 如下的vscode配置, 没有格式化css文件的效果,该怎么解决?
{
"files.eol": "\n",
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
发现css文件的格式化配置特殊一些, 要单独配置一条,格式化才有效果。
{
"files.eol": "\n",
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
}
13. dev环境的H5页面分享出去之后,打不开,是怎么回事?
这是因为dev环境的站点基础路径中含有wxwork字样, 而这个站点需要进行微信JS-SDK的初始化,在微信授权页面,因为redirect重定向地址中含有wxwork字样, 微信官方感觉回跳地址是钓鱼网站,阻断了重定向。所以一直卡在这一步,过不去。表现出来的现象就是页面打不开。解决方法就是修改跳转链接路径,移除wxwork字样。
12. 同样是使用whistle工具,为什么连接有的WiFi,抓包正常,连接有的WiFi,抓包不正常?
手机和PC端电脑连接同一个WiFi的前提下,whistle能否正常抓包,主要看连接的WiFi,是否需要进行用户身份认证。如果需要进行用户身份认证,即便PC端电脑已对同一WiFi进行了上网认证,将PC端启动的whistle服务主机地址,配置到手机上连接的同一WiFi网络的网络代理中,你会发现,手机也上不了网。从而造成whistle无法正常抓包。那么如何解决这个问题? 将电脑上的WiFi共享成一个移动热点,用手机去连这个移动热点,然后手机WiFi配置代理却不能上网的问题就能迎刃而解,whistle抓包功能也正常了
11. 嵌套着的async/await, 是否有阻塞等待异步函数结果返回的效果?
如下, init和fooA都是async/await结构, init调用了fooA, fooA里面调用了barB, 执行到barB这一步,有没有阻塞等待效果,主要取决barB返回的是不是Promise函数,如果是Promise函数,就有阻塞效果,否则就没有阻塞效果。
const init=async()=>{
await fooA();
console.log('initA');
}
const fooA=async()=>{
await barB();
console.log('barB');
}
const barB=()=>{
return new Promise((rs,rj)=>{
rs('ok');
},3*1000)
}
init();
10. 一般情况下,是不能把.env.dev.local文件提交到代码仓库的,因为会影响构建dev环境部署包时的环境变量配置, 可这个文件本地开发时必用,应该提交到版本库,该如何解决这个冲突?
首先我们看一下环境变量的优先级,我们可以让.env.[mode].local和.env.[mode]中的mode不同名,就能很好解决这个问题。
### 环境变量优先级说明
1. ./.env.[mode].local
2. ./.env.[mode]
3. ./.env.local
4. ./.env
将本地运行的环境变量文件命名为.env.pcdev.local, 将构建dev环境部署包的环境变量命名为.env.dev, 这样两个环境变量就不会相互干扰,就可以将.env.pcdev.local提交到版本库。
"scripts": {
"start:dev": "nx serve --mode pcdev --project 项目名",
"build:dev": "nx build --mode dev --project 项目名",
// ...
}
9. The previous cherry-pick is now empty, possibly due to conflict resolution.是什么意思,如何解决?
命令行输出信息如下:
$ git cherry-pick fd327f76
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:
git commit --allow-empty
Otherwise, please use 'git cherry-pick --skip'
On branch release/drc-20230510
You are currently cherry-picking commit fd327f76.
(all conflicts fixed: run "git cherry-pick --continue")
(use "git cherry-pick --skip" to skip this patch)
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
nothing to commit, working tree clean
这是因为某次执行cherry-pick的时候,代码冲突了,解决完冲突之后,本地分支内容和cherry-pick之前相比没有变化。下一次再执行git cherry-pick的时候,由于此时还处于上次cherry-pick,会提示该信息,表示由于解决冲突造成上一次cherry-pick内容是空的。执行
git commit --allow-empty
表示允许空提交。你会发现git cherry-pick commitid就执行成功了。
8. 有些WiFi网络,连接的时候需要输入账号和密码,输入账号密码的登录界面弹不出来,如何找到登陆入口?
今天发现,WiFi认证页面入口找不到了,平时打开手机自带的浏览器,就会弹出WiFi的登录界面。今天死活不弹,一时间还不知道怎么联网了。突然看到手机顶部的状态栏,有一个问号标志的WiFi图标,点击了一下,WiFi登录界面就显示出来了。WiFi登录界面入口真是奇怪,大多数情况下打开系统浏览器会自动弹出,而有时候又不会。
7. sessionStorage是会话存储空间, 怎么理解会话的含义?
sessionStorage引入了一个浏览器窗口的概念,sessionStorage的生命周期是在仅在当前会话下有效。我们用一个例子说明一下当前会话的含义:
localStorage在A页面调试控制台执行localStorage.setItem('test','111'),设置一个本地存储变量。复制A页面的url,重新打开一个页签, 在页签的地址栏粘贴A页面的url, 刷新页面,打开调试窗口控制台,执行localStorage.getItem('test'),可以读取出'111';sessionStorage在A页面调试控制台执行sessionStorage.setItem('test','111'),设置一个会话存储变量。复制A页面的url,重新打开一个页签, 在页签的地址栏粘贴A页面的url, 刷新页面,打开调试窗口控制台,执行sessionStorage.getItem('test'),不能读取出'111';
6. 在手机企业微信中,打开一个H5页面,报服务器证书不可信,而且只有Android手机上报这个错误,苹果手机页面可以正常打开,该怎么处理?
因为在苹果手机可以正常打开,可以初步排除是网站本身出了问题,推测可能是网络抖动,造成页面加载出错,错误的页面被缓存了起来,造成二次打开的时候,页面依旧加载不出来。清除了一下企业微信的缓存之后,果然可以正常打开了。
- 企微清缓存操作路径:点击左上角的三横杠-->弹窗界面右下角的设置齿轮-->通用-->存储空间
- 微信清缓存操作路径:我-->设置-->通用-->存储空间
5. ant-design-vue Table组件在控制台 打印出这样的警告warning.js:6 Warning: Index 7 of columns missing fixed='left' prop. , 该怎么处理?
这个警告的意思是,列表第八列的配置缺失fixed='left'属性, 我看了一下不是缺失fixed属性,看官方文档,fixed的值可以设置为true|left|right。把fixed配置成left|right都没问题,配成true控制台就会输出警告。那只能解释为,官方说明文档有误。
{
title: '操作',
key: 'action',
align: 'center',
width: 200,
// fixed: true,
},
4. ts类型定义,单独提取到一个文件好,还是定义到当前文件好?
实践证明,绝大多数情况下,把ts类型定义单独抽取到一个文件好,好处是:
- 阅读代码时,不会因为大段的ts类型定义,隔断了业务逻辑,造成阅读障碍。
- 复用比较方便,虽然把ts类型定义到当前文件也能进行类型复用,可是维护管理起来一团乱麻,存放散乱。
浏览器支持ES Modules,任何包含顶级 import 或者 export 的文件都被当成一个模块, 可以通过export声明导出模块, 通过import导入模块。代码要在一个不支持ES Modules的环境中运行,就无法使用模块系统了,不过ts是支持命名空间的,可以用命名空间,解决声明冲突。如果需要在外部调用 Home 中的类型定义,则需要在类型定义前添加 export 关键字。
namespace Home {
export interface Person {
name: string;
age: number;
}
}
3. 首页内容很多,网络不好的时候,加载很慢,最先展示的九宫格,如何让九宫格加快加载,优化首页展示体验?
九宫格区域的数据是从后端接口拉取的,这个区域一般不经常改动。基于这样的情况,可以把后端的接口数据使用localStorage保存在本地,每次先用本地数据渲染页面,等接口数据返回后,判断一下数据是否有变更,如果有变更,就重新渲染九宫格,以及更新本地的缓存数据。如果没有变更,就不做任何修改。经过这样的修改之后,一进入页面九宫格立刻就能呈现出来,给人感觉页面加载很快。
2. 对于对象类型的数组,要从中查找多个key对应的value, 怎样查找效果比较高?
例如下方的对象数组,要查询A1,A2,A4对应的value值,怎样查找比较方便?
const arr=[
{key:'A1',value:'V1'},
{key:'A2',value:'V2'},
{key:'A3',value:'V3'},
{key:'A4',value:'V4'},
// ...
];
我能想到的一个思路是,先将对象数组转换成对象,对象的key是对象数组每项的key,这样查找就会方便很多。
const obj=arr.reduce((acc,cur)=>{
acc[cur.key]=cur.value;
return acc;
},{});
1. 代码还没修改完,编译器就开始重新编译,导致控制台报错,如何优化这种情况?
如下,还在修改中,引起一长串编译报错,看着令人感到心烦意乱。我想到的一个方法就是,先把要修改的那一大段代码注释起来,在注释状态下进行修改,修改完之后再把注释打开,这样就不会在修改的过程中出现编译报错了。