Skip to main content

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/

image-20220725221638337

[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)

image-20220725221607388

[3][在线aes装换](https://the-x.cn/cryptography/Aes.aspx)

image-20220725221535025

2 Algolia爬虫

https://crawler.algolia.com

image-20220725230023083

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 元素在页面移动

https://sui.io/

image-20220727220815150

原理

@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树生成顺序

image-20220727234912629

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)