Record
asset references
ref -> reference
该 tc39 的提议中提议实现一种语法来引入asset类型文件
get first class references to a module identity without actually loading or initializing that module
That “asset” could be another ECMAScript module. Unlike import
, the asset
statement doesn’t actually load the other module. It’s just a reference to it. This reference can be passed to any dynamic import
call to actually load it and asynchronously resolve it to a module instance.
只做引用,不做使用
async function Bar() {
let foo = await import(Foo);
}
关于用 import 语法来引入 asset 类文件一直很让人困惑,因为 asset 的加载以及处理方式明显跟 js 类文件是完全不同的,问题在于 es 的语法暂无法区分,所以使用了 import 语法。
其他工作则由 webpack 来处理了,无论是将import 转为返回 url string,还是转为 base64。
通过类似这样的额外语法,可以让 asset 类文件的引入更清晰,而且这样的引入就是单纯的引入,后续的如何转化,如何处理,则交由使用者来进行。
https://github.com/tc39/proposal-asset-references
如何了解es最新提案
https://juejin.cn/post/6844904030838194189#heading-5
First Class 的概念
https://developer.mozilla.org/zh-CN/docs/Glossary/First-class_Function
First Class: 该类型的值可以作为函数的参数和返回值,也可以赋给变量。
Second Class: 该类型的值可以作为函数的参数,但不能从函数返回,也不能赋给变量。
Third Class: 该类型的值作为函数参数也不行
多数程序语言中的整型、字符类型都是First Class的。
断点调试
DOM breakpoint
在 Elements 面板,右键点击节点唤出菜单,添加对应的 DOM 断点,可以监测指定节点的子树修改、属性修改、以及节点的移除。
Source breakpoint
无需在源码中添加 debugger。直接在 Source 面板添加断点即可调试。见下图行号上的小蓝色箭头!
Conditional breakpoint
条件断点。只有符合条件时,才会触发断点
除此之外,还有 blackbox、XHR(fetch) breakpoint 等各种 Chrome 提供的工具
TypeScript
index signature
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
https://github.com/Microsoft/TypeScript/issues/24220
目前的 索引签名还是有所限制的,如不能是一个 union,得用 key in 代替:
这种写法叫 mapped type
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
目前正在优化中:https://github.com/microsoft/TypeScript/pull/26797
完成后可以拥有更加自由的 index 类型写法。
ts 需求计划表
https://github.com/microsoft/TypeScript/wiki/Roadmap#43-may-2021
React
render-props用hook代替
如果render-props调用相当于传递一个函数 children,加计算衍生props,完全可以将计算用 props 传递给 useXX function 再调用 children 来实现。
const Toggle = ({children, ...props}) => children(useToggle(props))
render-props的不可替代的用处是 让 子组件 自行选择使用复用块(inversion of control) 的内容。且这样的选用过程是可以出现在一个独立的函数scope中的,相比 hooks 需要侵占组件 scope 的空间,实际会看上去舒服点。
原先的逻辑复用,尤其是 props衍生和独立状态管理 的复用部分已经完全可以被hooks所取代了。
children 不变,则 children 不会重渲染
该优化方式与将 JSX 通过 props 传递是一样的意思,可以作为后期优化点,前期未出现性能问题时,实无需关注。
如果 ExpensiveTree 未使用 memo包裹,每次set后的 rerender,都会导致无效渲染:
function ExpensiveTree() {
console.log('render')
let now = performance.now();
while (performance.now() - now < 100) {
// Artificial delay -- do nothing for 100ms
}
return <p>I am a very slow component tree.</p>;
}
export default function App() {
let [color, setColor] = useState('red');
return (
<div style={{ color }}>
<input value={color} onChange={(e) => setColor(e.target.value)} />
<p>Hello, world!</p>
<ExpensiveTree />
</div>
);
}
但如果把不需要使用到 color 这个状态的内容放到 childern 中,set 后的 rerender 在 ColorPicker 中发生,children 返回的 JSX 未做变化,children 则不会被重新渲染:
function ColorPicker({ children }) {
let [color, setColor] = useState("red");
return (
<div style={{ color }}>
<input value={color} onChange={(e) => setColor(e.target.value)} />
{children}
</div>
);
}
export default function App() {
return (
<ColorPicker>
<p>Hello, world!</p>
<ExpensiveTree />
</ColorPicker>
);
}
但这个优化点会被 render-props 打破,因为childern() 的调用,必然导致 children 内的内容重新渲染。所以最简单的方式还是都先用 memo 包,至少不会有问题。
export default function App() {
return (
<ColorPicker>
{() => {
return (
<>
<p>Hello, world!</p>
<ExpensiveTree />
</>
)
}}
</ColorPicker>
);
}
function ColorPicker({ children }) {
let [color, setColor] = useState("red");
return (
<div style={{ color }}>
<input value={color} onChange={(e) => setColor(e.target.value)} />
{children()}
</div>
);
}
function ExpensiveTree() {
console.log('render')
let now = performance.now();
while (performance.now() - now < 100) {
// Artificial delay -- do nothing for 100ms
}
return <p>I am a very slow component tree.</p>;
}