Live Note

Remain optimistic

  • before: abcd
  • after: acdb

===第一轮遍历开始===

a(之后)vs a(之前)
key 不变,可复用
此时 a 对应的 oldFiber(之前的 a)在之前的数组(abcd)中索引为 0
所以 lastPlacedIndex = 0;

继续第一轮遍历…

c(之后)vs b(之前)
key 改变,不能复用,跳出第一轮遍历
此时 lastPlacedIndex === 0;
===第一轮遍历结束===

===第二轮遍历开始===
newChildren === cdb,没用完,不需要执行删除旧节点
oldFiber === bcd,没用完,不需要执行插入新节点

将剩余 oldFiber(bcd)保存为 map

// 当前 oldFiber:bcd
// 当前 newChildren:cdb

继续遍历剩余 newChildren

key === c 在 oldFiber 中存在
const oldIndex = c(之前).index;
此时 oldIndex === 2; // 之前节点为 abcd,所以 c.index === 2
比较 oldIndex 与 lastPlacedIndex;

如果 oldIndex >= lastPlacedIndex 代表该可复用节点不需要移动
并将 lastPlacedIndex = oldIndex;
如果 oldIndex < lastplacedIndex 该可复用节点之前插入的位置索引小于这次更新需要插入的位置索引,代表该节点需要向右移动

在例子中,oldIndex 2 > lastPlacedIndex 0
lastPlacedIndex = 2;
c 节点位置不变

继续遍历剩余 newChildren

// 当前 oldFiber:bd
// 当前 newChildren:db

key === d 在 oldFiber 中存在
const oldIndex = d(之前).index;
oldIndex 3 > lastPlacedIndex 2 // 之前节点为 abcd,所以 d.index === 3
lastPlacedIndex = 3;
d 节点位置不变

继续遍历剩余 newChildren

// 当前 oldFiber:b
// 当前 newChildren:b

key === b 在 oldFiber 中存在
const oldIndex = b(之前).index;
oldIndex 1 < lastPlacedIndex 3 // 之前节点为 abcd,所以 b.index === 1
则 b 节点需要向右移动
===第二轮遍历结束===

最终 acd 3 个节点都没有移动,b 节点被标记为移动

parseInt 中塞 number

1
2
parseInt(0.000001) // 0
parseInt(0.0000001) // 1

为什么会得到这样的结果?

  1. parseInt(arg: string):接收的是一个string变量。
  2. 0.0000001转成string会变为1e-7
  3. parseInt('1e-7')结果为1

所以要截取小数,最好还是使用Math.trunc(n)

useRef

  • mutable ref
  • presist

eg: 实现一个需求:点击按钮时 input 自动聚焦。

  • createRef 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const HomePage = () => {
const input = createRef<HTMLInputElement>()

const handle = () => {
if (input.current) {
input.current.focus()
}
}

return (
<div>
<input ref={input} />
<button onClick={handle}>focus</button>
</div>
)
}
  • useRef 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const HomePage = () => {
const input = useRef<HTMLInputElement | null>(null)

const handle = () => {
if (input.current) {
input.current.focus()
}
}

return (
<div>
<input ref={input} />
<button onClick={handle}>focus</button>
</div>
)
}

两者的区别在于:createRef 每次渲染会返回一个新的引用,而 useRef 返回的是相同的引用(persist)。对于函数式组件,每次 useState 会造成整个组件的重新渲染,但是 uesRef 可以保证引用不变,不会触发 re-render。

Read more »

Overview

随着消费者支付习惯的改变,现金的存在作用在不断弱化。无现金交易将成为下一个支付前沿。目前多国央行在筹备发行数字货币,数字货币的稳定性和安全性,是各国央行研发的重中之重。

Read more »

函数的默认值

在 ES6 之前,不能直接为函数指定默认值,只能采用变通的方法:

1
2
3
4
5
6
7
8
function log(x, y) {
if (y === "undefined") {
y = "world"
}
console.log(x, y)
}
log("hello") //hello test
log("hello", "") //hello

ES6 允许为函数的参数设置默认值:

1
2
3
4
5
6
7
8
9
10
11
12
function log(x, y = "world") {
console.log(x, y)
}
log("hello") //hello world
log("hello", "") //hello

eg: function Point(x = 0, y = 0) {
this.x = x
this.y = y
}
let p = new Point()
console.log(p.x + " " + p.y) //0 0
Read more »