React
Fiber
react16.8 架构
react将HTML文档 (转成对象 AST)抽象语法树
function createElement(type, props, ...children) {
return {
type,
props: {
...props,
children: children.map(child =>
typeof child === 'object' ? child : createTextNode(child)
),
},
};
}
function createTextNode(text) {
return {
type: 'TEXT_ELEMENT',
props: {
nodeValue: text,
children: [],
},
}
手写 render (转成 dom)
reactDOM.render(<App />, document.getElementById("root"));
function render(vDom, container) {
let dom;
if (typeof vDom !== "object") {
dom = document.createTextNode(vDom);
} else {
dom = document.createElement(vDom.type); //<p>111</p>
}
if (vDom.props) {
Object.keys(vDom.props)
.filter((key) => key != "children")
.forEach((item) => {
dom[item] = vDom.props[item];
});
} //<p className="test">111</p>
if (vDom.props && vDom.props.children && vDom.props.children.length) {
vDom.props.children.forEach((child) => render(child, dom));
} //<p className="test">111</p>
container.appendChild(dom);
}
为什么需要 fiber
-
VDOM=>DOM renderer 渲染器 reconciler diff VDOM => create DOM 同步执行(render)
-
Fiber 是 React 中用于实现调度和协调的一种新的 reconciler 架构。它是在 React 16 中引入的,旨在解决 React 中长时间运行的任务阻塞主线程的问题,提高应用的性能和响应性。
注意:requestIdleCallback 是浏览器提供的一个 API,它允许开发者在浏览器空闲时间执行任务。但是,它并不是一个可靠的 API,因为浏览器的空闲时间可能会受到很多因素的影响,比如用户的操作、网络状况等。因此,React 团队自己实现了一个调度器,用于更可靠地管理和调度任务。 3. 原因: 控制精细度:React需要比它更高的控制精细度。他基于浏览器的空闲时间进行调度,而React 调度器可以根据组件优先级、更新的紧急程度等信息,更精确地安排渲染工作。 跨浏览器兼容性:React需要一个能够跨各个版本或框架的解决方案,以实现一致的性能体验。
1.同步不可中断执行->异步可中断 3. scheduler 任务的优先级 _UN_SAVE_componentWillMount
Fiber 达到的目的,需要解决两个问题
- 新的任务调度,有高优先级任务的时候将浏览器空了再继续执行 2.新的数据结构,可以随时中断,下次进来可接着执行
Fiber 架构
-
Fiber 架构是一种新的 React 架构,它将渲染过程分解为多个小的任务,并且可以在任务之间进行中断和恢复,从而提高了应用的性能和响应性。
-
Fiber 架构的核心思想是将渲染过程分解为多个小的任务,每个任务都可以在浏览器空闲时间执行,从而避免了长时间运行的任务阻塞主线程的问题。Fiber 架构还引入了新的数据结构,使得任务可以随时中断和恢复,从而提高了应用的性能和响应性。
<div>
<p>
<span></span>
<text></text>
</p>
</div>
div->p:child->span:child->sibling->text=>return
受控组件和非受控组件的理解
- 受控组件(推荐使用受控组件实现表单) 受代码控制的组件,组件状态全程响应外部数据 例如:input textarea select
- 非受控组件(控制能力比较弱) 不受代码控制的组件,组件状态不响应外部数据,需要手动获取组件状态 例如:input textarea select 通过 ref 获取最新的值
应用场景
非受控组件不能实现
实时校验
React 事件机制
React 事件机制的工作原理如下:
- 当用户与 React 组件交互时,React 会将事件封装成一个合成事件对象,并将其传递给相应的事件处理函数。
- 事件处理函数可以在组件中定义,并在其中执行相应的操作,比如更新组件的状态或调用其他函数。
- React 事件机制还支持事件冒泡和事件捕获,允许开发者在组件中定义多个事件处理函数,并在事件发生时执行相应的操作。
执行顺序
- 原生事件:子元素 DOM 事件监听
- 原生事件:父元素 DOM 事件监听
- React 事件:子元素事件监听
- React 事件:父元素事件监听
- 原生事件: document DOM 事件监听 react 所有的事件挂在到 document 对象上 先触发真实 DOM 事件再触发 react 事件 最后真正执行 document 上挂在的事件 组织事件冒泡 阻止合成事件冒泡 e.stopPropagation() 阻止原生事件冒泡 e.nativeEvent.stopImmediatePropagation() 阻止原生事件冒泡 e.nativeEvent.stopPropagation() 阻止默认行为 e.preventDefault() 合成事件:react 事件 原生事件:真实 DOM 事件 事件合成:react 事件和真实 DOM 事件合成一个事件对象
使用 css 方式
- .module.css 只作用于当前组件
- styled-components
- css in js
- css modules
- css in js
- less
- sass
- stylus
真实 DOM 和虚拟 DOM 的区别
真实 DOM 文档对象模型 虚拟 DOM 对真实 DOM 的描述
const vDom = <h1 className="text">hello</h1>;
const root = document.getElementById("root");
ReactDOM.render(vDom, root);
const vDom = React.createElement("h1", { className: "text" }, "hello");
区别
虚拟 Dom 不会重排和重绘,跨平台 真实 Dom 反之
用户权限
后端返回 router list 根据 role 展示不同页面 react-router onEnter
<router patch="/home" component={App} onEnter={(nextState, replace) => {
const uid=util.getUrlParams(nextState,"uid");
if(!uid){
replace("/login");
}else{
}
} />
动态组件(组件懒加载)
const comp = React.lazy(() => import("./components/xxx"));
function a() {
return (
<div>
<suspense fallback={<div>loading...</div>}>
<comp />
</suspense>
</div>
);
}
react设计思想
- 组件化 开闭原则 封闭:组件内部状态自身维护,只处理内部渲染逻辑 开放:组件通信,不同组件props 单向数据流进行交互
- 数据驱动视图 不直接操作 DOM,通过数据驱动视图更新
- 虚拟Dom 对真实dom进行映射,更新的时候进行两次进行diff算法比较,增量更新
HOC 高阶组件
function withLogin(WrappedComponentA) {
return WrappedComponentA;
}
原因 1.抽离重复代码,实现组件复用 2.条件渲染,渲染拦截 3.拦截组件的生命周期
属性代理
1.props
function HOC(WrappedComponentA) {
const newProps = { type: "HOC" };
return (props) => <WrappedComponentA {...props} {...newProps} />;
}
2.条件渲染
function HOC(WrappedComponentA) {
return (props) => (props.isShow ? WrappedComponentA : <p>empty</p>);
}
3.外部逻辑的封装