-什么是JSX

JavaScript XML。一种在React组件内部构建标签的类XML语法。JSX为react.js开发的一套语法糖,也是react.js的使用基础。React在不使用JSX的情况下一样可以工作,然而使用JSX可以提高组件的可读性,因此推荐使用JSX。

1
2
3
4
5
6
7
8
9
10
class MyComponent extends React.Component {
render() {
let props = this.props;
return (
<div className="my-component">
<a href={props.url}>{props.name}</a>
</div>
);
}
}

优点:
1.允许使用熟悉的语法来定义 HTML 元素树;
2.提供更加语义化且移动的标签;
3.程序结构更容易被直观化;
4.抽象了 React Element 的创建过程;
5.可以随时掌控 HTML 标签以及生成这些标签的代码;
6.是原生的 JavaScript。


-什么是虚拟DOM

虚拟DOM(VDOM)它是真实DOM的内存表示,一种编程概念,一种模式。它会和真实的DOM同步,比如通过ReactDOM这种库,这个同步的过程叫做调和(Reconciliation)
虚拟DOM更多是一种模式,不是一种特定的技术。


-为什么虚拟DOM会提高性能

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。


-React diff原理

把树形结构按照层级分解,只比较同级元素。
给列表结构的每个单元添加唯一的 key 属性,方便比较。
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.
选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。


-React中key的作用是什么

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。

1
2
3
4
5
6
7
8
9
render () {
return (
<ul>
{this.state.todoItems.map(({item, key}) => {
return <li key={key}>{item}</li>
})}
</ul>
)
}

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。


-为什么不直接更新state状态

如果进行如下方式更新状态,那么它将不会重新渲染组件。

1
2
//Wrong
This.state.message =”Hello world”;

而是使用 setState() 方法。它计划对组件状态对象的更新。状态改变时,组件通过重新渲染做出响应

1
2
//Correct
This.setState({message: ‘Hello World’});

注意:可以分配状态的唯一位置是构造函数。


-调用setState之后发生了什么

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。


-为什么建议传递给setState的参数是一个callback

为什么建议传递给setState的参数是一个callback而不是一个对象?
因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个state。


-React生命周期函数(v16.4)

1.constructor(props)

react组件的构造函数在挂载之前被调用。在实现React.Component构造函数时,需要先在添加其他内容前,调用super(props),用来将父组件传来的props绑定到这个类中,使用this.props将会得到。

官方建议:不要在constructor引入任何具有副作用和订阅功能的代码,这些应当在componentDidMount()中写入。

constructor中应当做些初始化的动作,如:初始化state,将事件处理函数绑定到类实例上,但也不要使用setState()。如果没有必要初始化state或绑定方法,则不需要构造constructor,或者把这个组件换成纯函数写法。

当然也可以利用props初始化state,在之后修改state不会对props造成任何修改,但仍然建议大家提升状态到父组件中,或使用redux统一进行状态管理。

1
2
3
4
5
6
constructor(props) {
super(props);
this.state = {
color: props.initialColor
};
}

2.static getDerivedStateFromProps(nextProps, prevState)

getDerivedStateFromProps在组件实例化后,和接受新的props后被调用。他返回一个对象来更新状态,或者返回null表示新的props不需要任何state的更新。

如果是由于父组件的props更改,所带来的重新渲染,也会触发此方法。调用setState()不会触发getDerivedStateFromProps()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
constructor(props) {
super(props);
this.state = {
list: [],
}
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log('up',props, state.list)
if (state.list.length === 0) {
console.log('down',props.list, state.list)
return {list : props.list}; //props.list
}
return null;
}

componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)

官方建议使用getDerivedStateFromProps函数代替componentWillReceiveProps()。当组件挂载后,接收到新的props后会被调用。如果需要更新state来响应props的更改,则可以进行this.props和nextProps的比较,并在此方法中使用this.setState()

如果父组件会让这个组件重新渲染,即使props没有改变,也会调用这个方法。react不会在组件初始化props时调用这个方法。调用this.setState也不会触发。

3.render()

render()方法是必需的。当他被调用时,他将计算this.propsthis.state,并返回以下一种类型:

  • React元素通过jsx创建,既可以是dom元素,也可以是用户自定义的组件。
  • 字符串或数字他们将会以文本节点形式渲染到dom中。
  • Portalsreact16版本中提出的新的解决方案,可以使组件脱离父组件层级直接挂载在DOM树的任何位置。
  • 什么也不渲染
  • 布尔值 也是什么都不渲染,通常后跟组件进行判断。

当返回,false,ReactDOM.findDOMNode(this)将会返回null,什么都不会渲染。

render()方法必须是一个纯函数,他不应该改变state,也不能直接和浏览器进行交互,应该将事件放在其他生命周期函数中。 如果shouldComponentUpdate()返回falserender()不会被调用。

Fragments

你也可以在render()中使用数组,如:(不要忘记给每个数组元素添加key,防止出现警告)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
render() {
return [
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];

//换一种写法,可以不写key(v16++)

render() {
return (
<React.Fragment>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</React.Fragment>
);
}

4.componentDidMount()

仅在客户端的第一次渲染之后执行(组件真正在被装载之后)。

这是AJAX请求和DOM或状态更新应该发生的地方。此方法也用于与其他JavaScript框架以及任何延迟执行的函数(如 setTimeout 或 setInterval )进行集成,在这里使用它来更新状态,以便我们可以触发其他生命周期方法。

componentWillMount() / UNSAFE_componentWillMount()

componentWillMount()将在react未来版本中被弃用。UNSAFE_componentWillMount()在组件挂载前被调用,在这个方法中调用setState()不会起作用,是由于它在render()前被调用。

为了避免副作用和其他的订阅,官方都建议使用componentDidMount()代替。这个方法是用于在服务器渲染上的唯一方法。

5.shouldComponentUpdate(nextProps, nextState)

在未来版本,shouldComponentUpdate()将会作为一个提示而不是严格的指令,返回false仍然可能导致组件的重新渲染。官方并不建议在shouldComponentUpdate()中进行深度查询或使用JSON.stringify(),他效率非常低,并且损伤性能。

调用shouldComponentUpdate使react知道,组件的输出是否受state和props的影响。默认每个状态的更改都会重新渲染,大多数情况下应该保持这个默认行为。

在渲染新的propsstate前,shouldComponentUpdate会被调用。默认为true。这个方法不会在初始化时被调用,也不会在forceUpdate()时被调用。返回false不会阻止子组件在state更改时重新渲染。如果shouldComponentUpdate()返回false,componentwillupdate,render和componentDidUpdate不会被调用。

componentWillUpdate/UNSAFE_componentWillUpdate(nextProps, nextState)

在渲染新的state或props时,UNSAFE_componentWillUpdate会被调用,将此作为在更新发生之前进行准备的机会。这个方法不会在初始化时被调用。

不能在这里使用this.setState(),也不能做会触发视图更新的操作。如果需要更新state或props,调用getDerivedStateFromProps。

6.getSnapshotBeforeUpdate()

render()后的输出被渲染到DOM之前被调用。

它使您的组件能够在它们被潜在更改之前捕获当前值(如滚动位置)。这个生命周期返回的任何值都将作为参数传递给componentDidUpdate()

7.componentDidUpdate(prevProps, prevState, snapshot)

在更新发生后立即调用componentDidUpdate()。此方法不用于初始渲染。当组件更新时,将此作为一个机会来操作DOM。只要您将当前的props与以前的props进行比较(例如,如果props没有改变,则可能不需要网络请求),这也是做网络请求的好地方。

如果组件实现getSnapshotBeforeUpdate()生命周期,则它返回的值将作为第三个“快照”参数传递给componentDidUpdate()。否则,这个参数是undefined

8.componentWillUnmount()

在组件被卸载并销毁之前立即被调用。

在此方法中执行任何必要的清理,例如使定时器无效,取消网络请求或清理在componentDidMount()中创建的任何监听。

9.componentDidCatch(error, info)

错误边界是React组件,可以在其子组件树中的任何位置捕获JavaScript错误,记录这些错误并显示回退UI,而不是崩溃的组件树。错误边界在渲染期间,生命周期方法以及整个树下的构造函数中捕获错误。

如果类组件定义了此生命周期方法,则它将成为错误边界。在它中调用setState()可以让你在下面的树中捕获未处理的JavaScript错误,并显示一个后备UI。只能使用错误边界从意外异常中恢复;不要试图将它们用于控制流程。

错误边界只会捕获树中下面组件中的错误。错误边界本身不能捕获错误。


-React 性能优化是哪个周期函数

-shouldComponentUpdate是做什么的

shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。


-React中refs的作用是什么

Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CustomForm extends Component {
handleSubmit = () => {
console.log("Input Value: ", this.input.value)
}
render () {
return (
<form onSubmit={this.handleSubmit}>
<input
type='text'
ref={(input) => this.input = input} />
<button type='submit'>Submit</button>
</form>
)
}
}

上述代码中的 input 域包含了一个 ref 属性,该属性声明的回调函数会接收 input 对应的 DOM 元素,我们将其绑定到 this 指针以便在其他的类函数中使用。另外值得一提的是,refs 并不是类组件的专属,函数式组件同样能够利用闭包暂存其值:

1
2
3
4
5
6
7
8
9
10
11
function CustomForm ({handleSubmit}) {
let inputElement
return (
<form onSubmit={() => handleSubmit(inputElement.value)}>
<input
type='text'
ref={(input) => inputElement = input} />
<button type='submit'>Submit</button>
</form>
)
}

-如何创建refs

Refs 是使用 React.createRef() 方法创建的,并通过 ref 属性添加到 React 元素上。为了在整个组件中使用 refs ,只需将 ref 分配给构造函数中的实例属性

1
2
3
4
5
6
7
8
9
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}

-展示组件和容器组件之间有何不同

展示组件(Presentational component):展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态

容器组件(Container component):容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。


-类组件和函数组件之间有什么区别

无论是使用函数或是类来声明一个组件,它决不能修改它自己的 props 。所有 React 组件都必须是纯函数,并禁止修改其自身 props 。React是单项数据流,父组件改变了属性,那么子组件视图会更新。

类组件( Class components )
属性 props 是外界传递过来的,状态 state 是组件本身的,状态可以在组件中任意修改,组件的属性和状态改变都会更新视图。
类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态。

1
2
3
4
5
6
7
8
9
class Welcome extends React.Component {
render() {
return (
<h1>Welcome { this.props.name }</h1>
);
}
}
ReactDOM.render(<Welcome name='react' />,
document.getElementById('root'));

函数组件(functional component)
该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。

1
2
3
4
5
6
7
8
9
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);

区别

函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。

函数组件,类组件
是否有this?没有,有
是否有生命周期?没有,有
是否有状态state?没有,有

当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 无状态组件(stateless component),可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件dumb components展示组件(Presentational component)

为了提高性能,尽量使用函数组件。


-组件的状态(state)和属性(props)之间有何不同

stateprops 都是普通的JavaScript对象。尽管它们两者都具有影响渲染输出的信息,但它们在组件方面的功能不同。

props(properties 的简写)是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性(immutable),只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。
组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据–回调函数也可以通过 props 传递。

state 的主要作用是用于组件保存、控制以及修改自己的状态,它只能在 constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的setState() 来修改,修改 state 属性会导致组件的重新渲染。


-何为受控组件(controlled component)

HTML 中,类似 <input>, <textarea><select> 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一起被发送。

但在 React 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 更新 state,重新渲染组件。一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为"受控元素"

受控组件

受控组件就是组件的状态受React控制。上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Demo extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
}

handleChange(e) {
this.setState({
value: e.target.value
})
}

render() {
return (
<input value={this.state.value}
onChange={e => this.handleChange(e)}/>
)
}
}

非受控组件

非受控组件,即组件的状态不受React控制的组件

1
2
3
4
5
6
7
8
9
10
11
12
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Demo extends Component {
render() {
return (
<input />
)
}
}

ReactDOM.render(<Demo/>, document.getElementById('content'))

在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。


-在构造函数中调用 super(props) 的目的是什么

super() 被调用之前,子类是不能使用 this 的,在 ES6 中,子类必须在 constructor 中调用 super()。传递 propssuper() 的原因则是便于(在子类中)能在 constructor 访问 this.props

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//使用props:
class MyComponent extends React.Component {
constructor(props) {
super(props);
console.log(this.props); // Prints { name: 'sudheer',age: 30 }
}
}
//不使用props:
class MyComponent extends React.Component {
constructor(props) {
super();
console.log(this.props); // Prints undefined
// But Props parameter is still available
console.log(props); // Prints { name: 'sudheer',age: 30 }
}

render() {
// No difference outside constructor
console.log(this.props) // Prints { name: 'sudheer',age: 30 }
}
}

上面的代码片段揭示了this.props行为仅在构造函数中有所不同,外部构造函数相同。


-何为高阶组件(higher order component)

高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。

高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。基本上,这是从React的组成性质派生的一种模式,我们称它们为 “纯”组件, 因为它们可以接受任何动态提供的子组件,但它们不会修改或复制其输入组件的任何行为。

最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。


-除了在构造函数中绑定 this,还有其它方式吗

你可以使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调。


-应该在 React 组件的何处发起 Ajax 请求

在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。


-描述事件在 React 中的处理方式

为了解决跨浏览器兼容性问题,您的 React 中的事件处理程序将传递 SyntheticEvent 的实例,它是 React 的浏览器本机事件的跨浏览器包装器。

这些 SyntheticEvent 与您习惯的原生事件具有相同的接口,除了它们在所有浏览器中都兼容。有趣的是,React 实际上并没有将事件附加到子节点本身。React 将使用单个事件监听器监听顶层的所有事件。这对于性能是有好处的,这也意味着在更新 DOM 时,React 不需要担心跟踪事件监听器。


-createElement 和 cloneElement 有什么区别

React.createElement():JSX 语法就是用 React.createElement()来构建 React 元素的。

它接受三个参数,第一个参数可以是一个标签名。如 div、span,或者 React 组件。第二个参数为传入的属性。第三个以及之后的参数,皆作为组件的子组件。

1
2
3
4
5
React.createElement(
type,
[props],
[...children]
)

React.cloneElement()与 React.createElement()相似,不同的是它传入的第一个参数是一个 React 元素,而不是标签名或组件。新添加的属性会并入原有的属性,传入到返回的新元素中,而就的子元素将被替换。

1
2
3
4
5
React.cloneElement(
element,
[props],
[...children]
)

-React中有三种构建组件的方式

React.createClass()、ES6 class 和无状态函数。


-以下使用React.createElement的等价项是什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//问题:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);

//以下等同于什么使用 React.createElement ?

//答:
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

-使用React Hooks有什么优势

hooks 是react 16.8 引入的特性,他允许你在不写class的情况下操作state和react的其他特性。

hooks 只是多了一种写组件的方法,使编写一个组件更简单更方便,同时可以自定义hook把公共的逻辑提取出来,让逻辑在多个组件之间共享。
比如你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其它转化为 class。现在你可以在现有的函数组件中使用 Hook。

ReactHooks的优点 :无需复杂的DOM结构,简洁易懂


-为什么类方法需要绑定

在JavaScript中, this 的值取决于当前上下文。在React类的组件方法中,开发人员通常希望它引用组件的当前实例,因此有必要 将 这些方法 绑定 到该实例。通常,这是在构造函数中完成的,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SubmitButton extends React.Component {
constructor(props) {
super(props);
this.state = {
isFormSubmitted: false
};
this.handleSubmit = this.handleSubmit.bind(this);
}

handleSubmit() {
this.setState({
isFormSubmitted: true
});
}

render() {
return (
<button onClick={this.handleSubmit}>Submit</button>
)
}
}

-简述 flux 思想

Flux 的最大特点,就是数据的”单向流动”。有四个组成部分 actiondispatcherviewstore

用户访问 View
View 发出用户的 Action
Dispatcher 收到 Action,要求 Store 进行相应的更新
Store 更新后,发出一个”change”事件
View 收到”change”事件后,更新页面


-简述 redux 思想

redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题。原理是集中式管理,主要有三个核心方法,actionstorereducer

view 调用 storedispatch 接收 action 传入 storereducer 进行 state 操作,
view 通过 store 提供的 getState 获取最新的数据,

ReduxFlux 很像。主要区别在于 Flux 有多个可以改变应用状态的 store,在 Flux 中 dispatcher 被用来传递数据到注册的回调事件,但是在 redux 中只能定义一个可更新状态的 storeredux 把 store 和 Dispatcher 合并,结构更加简单清晰。

一般情况下,我们在构建多交互,多数据流的复杂项目应用时才会使用它们。


-redux 有什么缺点

一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断。


-描述Flux与MVC

传统的MVC模式在分离数据(模型),UI(视图)和逻辑(控制器)的关注方面效果很好,但是MVC架构经常遇到两个主要问题:

  • 数据流定义不佳: 跨视图进行的级联更新通常会导致纠结的事件网,难以调试。
  • 缺乏数据完整性: 可以从任何地方对模型数据进行突变,从而在整个UI上产生不可预测的结果。

使用Flux模式,复杂的UI不再受到级联更新的困扰。任何给定的React组件都将能够根据商店提供的数据重建其状态。Flux模式还通过限制对共享数据的直接访问来增强数据完整性。


-React Context是什么

React文档官网并未对 Context 给出“是什么”的定义,更多是描述使用的 Context 的场景,以及如何使用 Context 。

官网对于使用 Context 的场景是这样描述的:
In Some Cases, you want to pass data through the component tree without having to pass the props down manuallys at every level. you can do this directly in React with the powerful "context" API.

简单说就是,当你不想在组件树中通过逐层传递 props 或者 state 的方式来传递数据时,可以使用 Context 来实现 跨层级 的组件数据传递。

  • 使用props或者state传递数据,数据自顶下流。
  • 使用 Context ,可以跨越组件进行数据传递。

-React Fiber是什么

React Fiber 并不是所谓的纤程(微线程、协程),而是一种基于浏览器的单线程调度算法,背后的支持 API 是大名鼎鼎的:requestIdleCallback

Fiberl是一种将 Reconciliation (递归 diff),拆分成无数个小任务的算法;它随时能够停止,恢复。停止恢复的时机取决于当前的一帧(16ms)内,还有没有足够的时间允许计算。



参考文章: