0%

慎用sessionStorage.clear():一个由全局清理引发的Token丢失问题

今天下午,我正在全神贯注地编写代码,测试组的一位同事突然找到我,说我的页面在发送请求的时候没有携带token,导致api调用出错。

我:不可能,token都是前端统一携带的,我的页面并无特殊处理,怎么可能没有携带token?

妹子:可是我在测试的时候发现确实没有携带token。

我:你确定是我的页面吗?

妹子:是的,你可以现在就看一下。

于是我F12打开浏览器的开发者工具,来到我的页面查看网络请求,果然发现请求头中没有携带token。气氛一度十分尴尬…

我:稍等,容我检查一下。

妹子没说话,可能觉得我刚才不够信任她…

经过一番调试,发现的确是我的问题,我这个页面比较特殊,是类似一个用户向导的功能,共分为三个步骤,每个步骤对应独立的页面,而且每个页面都需要用户填写一些信息,除了第一步之外,其他的步骤都支持后退修改。所有的步骤都支持取消操作,表示用户放弃了本次操作。

为了支持在最后一个页面提交,我使用了sessionStorage来存储用户填写的信息,如果用户在某个页面点击了取消按钮,那么我会清空sessionStorage中的数据。问题就出在这个清空操作上,我用的是sessionStorage.clear()方法,这个方法会清空整个sessionStorage,而不仅仅是我这个页面存储的数据。

巧合的是,前几天开发登录功能的小伙伴刚刚把存储token的代码从localStorage改成了sessionStorage,导致我在清空sessionStorage的时候也把token给清空了。于是就产生了妹子所说的没有携带token的问题。

解决的办法也很简单,就是把清空sessionStorage的代码改成只删除当前页面存储的数据,而不是清空整个sessionStorage。可以使用sessionStorage.removeItem('key')方法来删除指定的键值对。

1
2
// 清空当前页面存储的数据
sessionStorage.removeItem('userData');

这样就可以避免清空其他页面存储的数据,也不会影响到token的存储。

总结

慎用sessionStorage.clear()方法,它会清空整个sessionStorage,可能会导致其他页面存储的数据丢失。这个方法应用在关闭整个应用的时候做总的清理工作。

如果只是某个页面的清理工作,建议使用sessionStorage.removeItem('key')方法来删除指定的键值对,这样可以避免不必要的数据丢失。

最近使用React+Ant Design进行项目开发,单元测试的过程及其痛苦,尤其对于单元测试的覆盖率问题,一直无法达标,经常导致pipeline失败。

其实我们项目的单元测试覆盖率要求并不高,只有60%,之前的项目要求都是90%的。之所以覆盖率。

最近的项目使用阿里umijs框架,在做Unit Test时遇到了一些问题,在此记录一下,以供日后查阅。

创建Umi项目

使用以下命令创建一个新的Umi项目,项目模版选择ant-design-pro,npm client选择npm,npm registry选择npm

1
npx create-umi@latest

生成jest配置

Umi的方便之处是可以一键生成jest配置,只需运行如下命令即可:

1
npx umi g jest

运行测试

使用以下命令运行测试

Read more »

今天在玩耍typescript的时候,发现了一个有趣的问题,tsconfig.json中的outDir配置导致tsc命令无法编译,tsconfig.json的配置是这样的:

Read more »

今天来看一下如何在React项目中使用Jest进行单元测试。

创建React项目

我们使用Vite来创建React项目,命令如下:

1
npm create vite@latest react-app-jest --template react-ts

使用VSCode打开项目

使用如下命令打开项目

1
2
cd react-app-jest
code .
Read more »

今天来研究一下如何在Angular应用中集成Lit Element。Lit Element是一个轻量级的Web Component库,基于标准的Web Component API,因此可以在任何支持Web Component的框架中使用,比如React、Vue、Angular等。

使用Angular CLI创建Angular项目

如果你已经安装了Angular CLI,可以直接使用以下命令创建一个新的Angular项目:

1
ng new lit_element-app-angular

如果你没有安装过Angular CLI,也没关系,可以使用以下命令创建Angular项目:

1
npx @angular/cli@latest new lit_element-app-angular

在cli创建项目的过程中可能会提示你选择CSS预处理器,我们直接选择CSS即可,CLI还会询问是否启用服务端渲染,我们选择否。

安装Lit Element依赖

待项目创建好以后,我们使用如下命令用VSCode打开项目,首先使用cd lit_element-app-angular进入项目目录,然后使用code .表示用VSCode打开当前目录。

1
2
cd lit_element-app-angular
code .

打开VSCode中的Terminal,运行以下命令安装lit

1
npm install lit

创建Lit Element组件

src目录下创建一个components目录,然后在components目录下创建一个my-element.ts文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';

@customElement('my-element')
export class MyElement extends LitElement {
@property({ type: String }) name = 'World';

static override styles = css`
:host {
display: block;
padding: 16px;
color: var(--my-element-text-color, black);
}
`;

override render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}

使用my-element组件

首先:在src/app/app.component.ts中引入my-element.ts并添加CUSTOM_ELEMENTS_SCHEMA,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import '../components/my-element'; // 引入my-element组件
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
schemas: [CUSTOM_ELEMENTS_SCHEMA], // 添加CUSTOM_ELEMENTS_SCHEMA
})
export class AppComponent {
title = 'lit_element-app-angular';
}

然后:在src/app/app.component.html中使用my-element组件:

1
2
<my-element name="World"></my-element>
<router-outlet />

更新tsconfig设置

打开项目根目录下(package.json所在目录)的tsconfig.app.json文件,添加以下配置:

1
2
3
4
5
6
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false
}
}

运行项目

1
npm run start

在浏览器中访问http://localhost:4200,你应该能看到如下效果:

1
Hello, World!

话说Angular集成Lit简直是分分钟的事,比React简单太多了。为什么国内用Angular的人这么少呢?不理解…

分支的本质是什么?

分支的本质是一个指向某个commit的指针。所以未commit的修改是没有分支的概念的,只有commit才有分支的概念。

下面的命令中我们使用git checkout来切换分支,新版本的git推荐使用git switch来切换分支。但是git checkout命令还有其他功能,比如检出某个版本,所以git switch命令并不能完全替代git checkout命令。

Read more »

VSCode是时下最令行的前端开发工具,用好VSCode能极大的提高我们的开发效率,而搜索是日常开发中必不可少的操作,今天我们一起来聊聊VSCode中的搜索技巧。

普通的搜索我们就不谈了,今天主要介绍一下正则表达式搜索和一些小技巧。

匹配换行符

  • [.|\n]* - 可以匹配任意字符,包括换行符。
  • [\s\S] - 注意这种方式不好用。

一般情况下我们都是进行单行搜索,但是有些情况下我们需要跨行搜索,比如下面的React代码:

1
2
3
4
useEffect(() => {
const lang = LocalStorageUtil.getLanguage();
i18n.changeLanguage(lang);
}, []);

如果我想搜索所有依赖数组为空的useEffect调用,该怎么写这个正则表达式呢?大家可以先试试,反正我试了半天也没写出来,后来还是差DeepSeek才搞定,答案如下:

1
useEffect\((.|\n)*?,\s*\[\s*\]\s*\)

我们来解析一下这个正则表达式:

  • useEffect - 匹配useEffect字符串
  • \( - 匹配(字符,因为(是正则表达式中的特殊字符,所以需要转义。
  • (.|\n)*? - 匹配任意字符,包括换行符,*?表示非贪婪匹配,尽可能少的匹配字符。
  • , - 匹配,字符
  • \s* - 匹配,[]之间的任意空格字符,包括空格、制表符、换行符等,*表示匹配0次或多次。
  • \[\s*\] - 匹配空的依赖数组,因为[]是正则表达式中的特殊字符,所以需要转义。
  • \s*\) - 匹配最后的右括弧,\s*表示[]与右括弧之间可能有空格。

这里面的关键是:(.|\n) - 它匹配任意字符包括换行符。

匹配markdown中的表格

在Markdown中,使用如下方式来生成表格。

1
2
3
4
| Name  | Age |
| ----- | --- |
| Tom | 18 |
| Jerry | 20 |

如果我们要查找所有的markdown表格,那么我们只需要找出如下特征字符串即可

1
|------|-----|

可以使用如下的正则表达式:

1
\|\s*-+

我们来解析一下这个正则表达式:

  • \| - 匹配|字符,因为|是正则表达式中的特殊字符,所以需要转义。
  • \s* - 匹配|-之间的任意空格字符。
  • -+ - 匹配-字符,+表示匹配1次或多次。

这样,我们就可以查出所有的markdown表格了。你学会了吗?