7-23
1 前端AES加密
依赖
yarn add crypto-js
yarn add -D @types/crypto-js
示例
import CryptoJS from 'crypto-js'
const key = '6fa979f20126cb08aa645a8f495f6d85';
const iv = 'I8zyA4lVhMCaJ5Kg';
const utf8PubKeyArr = CryptoJS.enc.Utf8.parse(key)
const utf8IvArr = CryptoJS.enc.Utf8.parse(iv)
// Encrypt
export function getBase64AESCode(origin: string) {
const res = CryptoJS.AES.encrypt(origin, utf8PubKeyArr, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: utf8IvArr,
}).ciphertext
return CryptoJS.enc.Base64.stringify(res)
}
// Decrypt
export function parseBase64AESCode(base64Encrypted: string) {
const encrypted = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(base64Encrypted),
})
return CryptoJS.AES.decrypt(encrypted, utf8PubKeyArr, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: utf8IvArr,
}).toString(CryptoJS.enc.Utf8)
}
数据转换
在cryptojs中存在几种数据格式:
string
普通string,编码格式可能是utf8、GBK、GB2312等等
将string通过utf8去解析为WordArray
const arr = CryptoJS.enc.Utf8.parse('123')
WordArray
是一种通用格式
可以进行一些转换,示例见 https://www.cnblogs.com/qiqi715/p/9623421.html
CryptoJS.lib.CipherParams
生成一个CipherParams
const params = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse('123'),
})编码为utf8的string
一般高级类型(例如:WordArray、CipherParams),转化为string的时候可以选择编码格式
const arr = CryptoJS.enc.Utf8.parse('123')
arr.toString(CryptoJS.enc.Utf8)
=>> '123'
rsa256
rsa256通过 jsencrypt 包使用,但该包只能在客户端使用,无法正常用于nextjs,所以改用aes
参考
[1] https://cryptojs.gitbook.io/docs/
[2][CryptoJS encrypt in aes-256-cbc returns an unexpected value](https://stackoverflow.com/questions/57416217/cryptojs-encrypt-in-aes-256-cbc-returns-an-unexpected-value)
[3][在线aes装换](https://the-x.cn/cryptography/Aes.aspx)
2 Algolia爬虫
3 Eslint与mocha
让vscode识别mocha,.eslintrc
中:
"env": {
"commonjs": true,
"node": true,
"mocha": true
},
[1] https://stackoverflow.com/questions/30018271/javascript-standard-style-does-not-recognize-mocha
4 元素在页面移动
原理
@keyframe movingleftright3{
0% {
transform: translateX(0) translateY(0);
}
40% {
transform: translateX(100px) translateY(-200px);
}
75% {
transform: translateX(-500px);
}
100% {
transform: translateY(0) translateX(0);
}
}
animation: movingleftright3 20s infinite;
5 React的CreateElement
作用
CreateElement输入 type、props、children 用于创建如下结构:
type Element = {
type: string
props: Record<string, any>
}
可以看到与输入相比,输出结构中将 children 放到了props中
重点
如果是文本就创建一个文本节点
5 React的ConcurrentMode原理
核心点
在于两点:1.浏览器空闲时间 2.根据fiber创建dom
总结一句话:在浏览器有空闲时间时,根据fiber创建DOM
核心函数
function perForUnitWork(fiber) {
// 创建DOM
// 为当前fiber创建子fiber
// 返回下一个执行单元
if (!fiber.dom) {
fiber.dom = createDom(fiber)
}
if (fiber.parent) {
fiber.parent.dom.appendChild(fiber.dom)
}
const children = fiber.props?.children
let prevChild;
children && children.forEach((child, index) => {
const newFiber = {
parent: fiber,
type: child.type,
props: child.props,
dom: undefined
}
if (index === 0) {
fiber.child = newFiber
} else {
prevChild.sibling = newFiber
}
prevChild = newFiber
})
if (fiber.child) {
return fiber.child
}
let nextFiber = fiber
while (nextFiber) {
if (nextFiber.sibling) {
return nextFiber.sibling
}
nextFiber = nextFiber.parent
}
}
function workLoop(deadline) {
// 是否有空闲时间
// 是否有任务
// 渲染节点
let shouldYield = true
if (shouldYield && nextUnitWork) {
nextUnitWork = perForUnitWork(nextUnitWork)
shouldYield = deadline.timeRemaining > 1
}
requestIdleCallback(workLoop)
}
requestIdleCallback(workLoop)
Fiber
截止目前(2022-07-27 23:30:23),我了解的Fiber表示一种数据结构,如下:
type Fiber = {
type: string | () => any;
props: Record<string, any> & {
children: Element[]
};
dom: any;
parent: Fiber;
alternate: Fiber;
hooks: any[];
}
TODO 调研真正的Fiber结构
Fiber树生成顺序
5 React的render&commit
TODO
5 React的reconciliation
注意 元素
和 函数
的区别:
// 正确
const element = (
<div>
<input onInput={handleInput} value={value} />
<h1>内容:{value}</h1>
</div>
);
// 错误
const element =() =>{
return (
<div>
<input onInput={handleInput} value={value} />
<h1>内容:{value}</h1>
</div>
);
}
改变jsx创建元素函数:
/** @jsxRuntime classic */
/** @jsx MyReact.createElement */
import MyReact from "./lib";
const contianer = document.getElementById("root") as HTMLElement;
function handleInput(e: any) {
renderder(e.target.value);
}
function renderder(value: string) {
const element = (
<div>
<input onInput={handleInput} value={value} />
<h2>内容:{value}</h2>
</div>
);
MyReact.render(element, contianer);
}
renderder("嘻嘻");
5 React的hooks
TODO
6 React性能优化
- 一些性能优化API:useMemo、usecallback等
- 分离可变与不可变
分离可变与不可变
如下示例代码:
function A(){
const [value, setValue] = useState(0)
useEffect(()=>{
const timer = setInterval(()=> setValue(prev=>++prev), 1000)
return () => clearInterval(timer)
}, [])
return (
<div>
{value}
<B />
</div>
)
}
问:B组件会随着value变更而重新渲染吗?
会
解决方案:分离可变与不可变
将变的部分分离出来,C组件
function C() {
const [value, setValue] = useState(0);
useEffect(() => {
const timer = setInterval(() => setValue((prev) => ++prev), 1000);
return () => clearInterval(timer);
}, []);
return <>{value}</>;
}
function A() {
return (
<div>
<C />
<B />
</div>
);
}
[1][前端开发工程师如何写出高可维护的代码](https://www.bilibili.com/video/BV1H44y1u7Fk?p=5&spm_id_from=333.880.my_history.page.click&vd_source=4065bea3d3139c3fda8b128a6a3a90a7)