You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// ReactBaseClasses.js 文件/** * Base class helpers for the updating state of a component. */functionComponent(props,context,updater){this.props=props;// 属性 propsthis.context=context;// 上下文 context// If a component has string refs, we will assign a different object later.// 初始化 refs,为 {},主要在 stringRef 中使用,将 stringRef 节点的实例挂载在 this.refs 上this.refs=emptyObject;// We initialize the default updater but the real one gets injected by the// renderer.this.updater=updater||ReactNoopUpdateQueue;// updater}Component.prototype.isReactComponent={};/** * 设置 state 的子集,使用该方法更新 state,避免 state 的值为可突变的状态 * `shouldComponentUpdate`只是浅比较更新, * 可突变的类型可能导致 `shouldComponentUpdate` 返回 false,无法重新渲染 * Immutable.js 可以解决这个问题。它通过结构共享提供不可突变的,持久的集合: * 不可突变: 一旦创建,集合就不能在另一个时间点改变。 * 持久性: 可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用。 * 结构共享: 新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能。 * * 并不能保证 `this.state` 通过 `setState` 后不可突变的更新,它可能还返回原来的数值 * 不能保证 `setrState` 会同步更新 `this.state` * `setState` 是通过队列形式来更新 state ,当 执行 `setState` 时, * 会把 state 浅合并后放入状态队列,然后批量执行,即它不是立即更新的。 * 不过,你可以在 callback 回调函数中获取最新的值 * * 注意:对于异步渲染,我们应在 `getSnapshotBeforeUpdate` 中读取 `state`、`props`, * 而不是 `componentWillUpdate` * * @param {object|function} partialState Next partial state or function to * produce next partial state to be merged with current state. * @param {?function} callback Called after state is updated. * @final * @protected */Component.prototype.setState=function(partialState,callback){// 当 partialState 状态为 object 或 function类型 或 null 时,// 执行 this.updater.enqueueSetState 方法,否则报错invariant(typeofpartialState==='object'||typeofpartialState==='function'||partialState==null,'setState(...): takes an object of state variables to update or a '+'function which returns an object of state variables.',);// 将 `setState` 事务放入队列中this.updater.enqueueSetState(this,partialState,callback,'setState');};/** * 强制更新,当且仅当当前不处于 DOM 事物(transaction)中才会被唤起 * This should only be invoked when it is known with * certainty that we are **not** in a DOM transaction. * * 默认情况下,当组件的state或props改变时,组件将重新渲染。 * 如果你的`render()`方法依赖于一些其他的数据, * 你可以告诉React组件需要通过调用`forceUpdate()`重新渲染。 * 调用`forceUpdate()`会导致组件跳过 `shouldComponentUpdate()`, * 直接调用 `render()`。但会调用 `componentWillUpdate` 和 `componentDidUpdate`。 * 这将触发组件的正常生命周期方法,包括每个子组件的 shouldComponentUpdate() 方法。 * forceUpdate 就是重新 render 。 * 有些变量不在 state 上,当时你又想达到这个变量更新的时候,刷新 render ; * 或者 state 里的某个变量层次太深,更新的时候没有自动触发 render 。 * 这些时候都可以手动调用 forceUpdate 自动触发 render * * @param {?function} callback 更新完成后的回调函数. * @final * @protected */Component.prototype.forceUpdate=function(callback){// updater 强制更新this.updater.enqueueForceUpdate(this,callback,'forceUpdate');};
一、组件
1. 纯组件
React.PureComponent
,和React.Component
类似,都是定义一个组件类。不同是React.Component
没有实现shouldComponentUpdate()
,而React.PureComponent
通过props
和state
的浅比较实现了。在下一节中将会详细介绍。
2. 函数组件
定义React组件的最简单方式就是定义一个函数组件,它接受单一的 props 并返回一个React元素。
3. 受控组件与非受控组件
受控和非受控主要是取决于组件是否受父级传入的 props 控制
用 props 传入数据的话,组件可以被认为是受控(因为组件被父级传入的 props 控制)。
数据只保存在组件内部的 state 的话,是非受控组件(因为外部没办法直接控制 state)。
受控组件
与 html 不同的是,在 React 中,
<input>
或<select>
、<textarea>
等这类组件,不会主动维持自身状态,并根据用户输入进行更新。它们都要绑定一个onChange
事件;每当状态发生变化时,都要写入组件的 state 中,在 React 中被称为受控组件。onChange & value 模式(单选按钮和复选按钮对应的是 checked props)
react通过这种方式消除了组件的局部状态,使得应用的整个状态可控。
注意
<input type="file" />
,它是一个非受控组件。可以使用计算属性名将多个相似的操作组合成一个。
非受控组件
非受控组件不再将数据保存在 state,而使用 refs,将真实数据保存在 DOM 中。
非受控组件是最简单快速的实现方式,项目中出现极简的表单时,使用它,但受控组件才是是最权威的。
通常指定一个 defaultValue/defaultChecked 默认值来控制初始状态,不使用 value。
非受控组件相比于受控组件,更容易同时集成 React 和非 React 代码。
使用场景
4. 有状态组件与无状态组件
有状态组件
通过 state 管理状态
无状态组件
输入输出数据完全由props决定,而且不会产生任何副作用。
5. 展示组件与容器组件
展示组件
展示组件指不关心数据是怎么加载和变动的,只关注于页面展示效果的组件。
容器组件
容器组件只关心数据是怎么加载和变动的,而不关注于页面展示效果。
6. 高阶组件
高阶函数的定义:接收函数作为输入,或者输出另一个函数的一类函数,被称作高阶函数。
对于高阶组件,它描述的便是接受 React 组件作为输入,输出一个新的 React 组件的组件。
更通俗的描述为,高阶组件通过包裹(wrapped)被传入的 React 组件,经过一系列处理,最终返回一个相对增强(enhanced)的 React 组件,供其他组件调用。使我们的代码更具有复用性、逻辑性和抽象特性,它可以对 render 方法做劫持,也可以控制 props 、state。
实现高阶组件的方法有以下两种:
WrappedComponent.displayName || WrappedComponent.name || 'Component';
7. Hook 组件
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
但与 class 生命周期不同的是,Hook 更接近于实现状态同步,而不是响应生命周期事件。
useLayoutEffect
与componentDidMount
、componentDidUpdate
的调用阶段是一样的。但是,我们推荐你一开始先用 useEffect,只有当它出问题的时候再尝试使用useLayoutEffect
componentDidMount
或componentDidUpdate
不同的是,Hook 在浏览器完成布局与绘制之后,传给useEffect
的函数会延迟调用,但会保证在任何新的渲染前执行useEffect
的思维模型中,默认都是同步的。副作用变成了 React 数据流的一部分。对于每一个useEffect
调用,一旦你处理正确,你的组件能够更好地处理边缘情况。二、Component 源码解读
首先看一下 React.Component 结构
其中
this.refs
值emptyObject
为:ReactNoopUpdateQueue
为:注意,React API 只是简单的功能介绍,具体的实现是在 react-dom 中,这是因为不同的平台,React API 是一致的,但不同的平台,渲染的流程是不同的,具体的 Component 渲染流程不一致,会根据具体的平台去定制。
组件生命周期请参考 Hooks 与 React 生命周期的关系
The text was updated successfully, but these errors were encountered: