react
参考资源
core-content
生命周期及渲染
要点
- 首次渲染,更新,卸载
- 父组件更新,子组件默认更新
- React.memo, useMeo, useCallback的使用时机
class组件
- class组件才有生命周期:constructor, render, componentDidMount, componentDidUpdate, componentWillUnmount, shouldComponentUpdate, getDerivedStateFromProps, getSnapshotBeforeUpdate, componentDidCatch, static getDerivedStateFromError
- https://juejin.cn/post/7096137407409422344#heading-0

函数式组件
- 函数式组件没有生命周期,参考:https://juejin.cn/post/6844903901620092941

渲染机制
- 组件渲染的核心机制: 父组件更新,子组件默认更新;
- React.memo: 用于函数式组件,用于优化子组件的渲染,在父组件更新时,子组件默认会更新,但是如果用react.memo包裹起来,就不会重新更新了;当组件的props没有变化时,就不会重新渲染,比如,组件的一个props时callback,这个时候引用变了,也会重新更新,父组件里可以用useCallback包裹起来,这样就不会重新更新了;对于比较繁杂的计算或者结果,可以用useMemo包裹起来,避免重复计算;useMemo和useCallback的区别是,useMemo是返回一个值,useCallback是返回一个函数;useEffect可能会有闭包陷阱的问题,可以用useRef来解决这个问题,useRef通过指针拿到的都是最新的值,useRef还可以拿到dom的引用;
- useEffect 是异步执行的,而useLayoutEffect是同步执行的。useEffect 的执行时机是浏览器完成渲染之后,而 useLayoutEffect 的执行时机是浏览器把内容真正渲染到界面之前,和 componentDidMount 等价。
react懒加载
- react懒加载的原理: https://juejin.cn/post/6844904191853494280;
react的事件机制
- https://juejin.cn/post/7068649069610024974;
- https://juejin.cn/post/6961398889635119111;
- https://juejin.cn/post/6909066790022676494;
react hook
- react hook使用: link1;
- react hook的原理: https://zhuanlan.zhihu.com/p/499764270;
https://github.com/tangzixuan/react-illustration-series;
副作用
- react组件的本质就是:ui=f(data), 跟着渲染和交互无关的都是副作用,组件是个纯函数;
- https://www.zhihu.com/question/303338688/answer/1753583388
- 那么常见的副作用有哪些: 在函数体内修改函数外变量的值,调用会产生副作用的函数, http请求, Date.now()、Math.random()等不确定性方法等等,总结:具有不确定性的操作,你都可以理解为是不纯的,不纯的那么意味可能带来副作用。
react hook 原理
- react hook的执行顺序,典型的是useEffect, useLayoutEffect
- react hook的原理: https://juejin.cn/post/6891577820821061646;
https://7kms.github.io/react-illustration-series/main/hook-summary/;
https://zhuanlan.zhihu.com/p/372790745;
组件的更新机制
- 组件的更新逻辑: 参考上述渲染逻辑;
- 节点更新机制,fiber 机制, diff算法,最小编辑距离;
- 原理:
参考1: https://juejin.cn/post/6844904061838295047 其中react部分; 参考2: 参考mini demo react的实现;
mini demo react
- 参考: https://juejin.cn/post/6844904061838295047https://juejin.cn/post/7173341317395644429
https://github.com/BetaSu/big-react
https://github.com/zh-lx/mini-react
react组件的状态管理
- 基本的方法:
提升到公共父组件 context api redux zustland recoil - react状态管理库:https://juejin.cn/post/7172509907403407391#heading-23;
- 原理: https://juejin.cn/post/6844904061838295047 其中redux部分;
redux
- redux的技巧: 大型react、redux项目, trace回溯技巧:window.REDUX_DEVTOOLS_EXTENSION_COMPOSE,设置trace =true, webpack打包要设置
--devtool source-map, 这样就可以看到dispatch的调用栈了;
react的事件机制
- react事件机制的原理: https://juejin.cn/post/7068649069610024974;
react router
- 原理: https://juejin.cn/post/6844904061838295047 其中router部分;
react ssr
简化题目
实现简化版的render和h函数
js
function h(tagName, attributes, children /* Your Code HERE */) {
/* Your Code HERE */
// 把vdom => element
let element = document.createElement(tagName);
for (const key of Object.keys(attributes)) {
// console.log(key)
if (key === "on") {
// element.setAttribute('click', attributes[key].click)
element.addEventListener("click", (event) => {
attributes[key].click();
});
}
element.setAttribute(key, attributes[key]);
}
if (Array.isArray(children)) {
// console.log('test1', children)
// element.appendChild(children)
for (const item of children) {
let childItem = item;
if (typeof item === "string") {
childItem = document.createTextNode(item);
}
element.appendChild(childItem);
}
} else if (typeof children === "string") {
// element.innerHtml = children
let childItem = document.createTextNode(children);
element.appendChild(childItem);
}
return element;
}
function patch(containerElement, element) {
/* Your Code HERE */
// element => container
if (containerElement) {
containerElement.innerHtml = "";
containerElement.appendChild(element);
}
}
const container = document.getElementById("container");
function handleClick() {
console.log("clicked");
}
const vnode = h(
"div",
{ id: "element", class: "two classes", on: { click: handleClick } },
[
h("span", { class: "text-class1" }, "This is black"),
" and this is just normal text",
h("a", { href: "/foo" }, "I'll take you places!"),
]
);
// Patch into empty DOM element
patch(container, vnode);