React是React库的入口。如果你通过使用
<script>标签的方式来加载React,则可以通过React全局变量对象来获得React的顶层API。但你使用 es6与npm时,可以通过编写import React from 'react'来引入它们。当你使用ES5与npm时,则可以通过编写var React = require('react')来引入它们。
React顶层API
概览
组件
使用React组件可以将UI划分为独立且可复用的代码片段,每部分都可独立维护。你可以通过React.Component或者React.PureComponent来定义React组件。 如果你不使用ES6的class,则可以使用create-react-class模块来替代。
创建React元素
使用JSX来编写你的UI组件。每个JSX元素都是调用React.createElement()的语法糖。一般来说,如果你使用了JSX,就不需要调用以下方法了。
- createElement()
- createFactory()
转换元素
React提供了几个用于操作元素的API:
- cloneElement()
- isValidElement()
- React.Children
Fragments
React还提供了用于减少不必要嵌套的组件
React.Fragment
Refs
- React.createRef()
- React.forwardRef()
Suspense
Suspense使得组件可以"等待"某些操作结束后,再进行渲染。目前,Suspense仅支持的使用场景是:通过React.lazy动态加载组件。
- React.lazy
- React.Suspense
Hook
Hook是React 16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。
- 基础Hook
- useState
- useEffect
- useContext
- 额外的Hook
- useReducer
- useCallback
- useMemo
- useRef
- useImperativeHandle
- useLayoutEffect
- useDebugValue
参考
React.Component
React.Component是使用ES classes方式定义React组件的基类:
class Greeting extends React.Component{
render(){
return <h1>hello</h1>
}
}React.PureComponent
React.PureComponent与React.Component很相似。两者的区别在于React.Component并未实现shouldComponentUpdate(),而React.PureComponent中以浅层对比prop和state的方式来实现该函数。 如果赋予React组件相同的props和state,render()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。
React.PureComponent中的shouldComponentUpdate仅作对象的浅层比较。如果对象中包含复杂的数据结果,则可能因为无法检查深层的差别,产生错误的比对结果。仅在你的props和state较为简单时,才使用React.PureComponent,或者在深层数据结果发生变化时调用forceUpdate()来确保组件被正确的更新。你也可以考虑使用immutable对象加速嵌套数据的比较。此外,React.PureComponent中的shouldComponentUpdate()将跳过所有子组件树的prop更新。因此,请确保所有的组件也都是"纯"的组件。
React.memo
const MyComponent = React.memo(function MyComponent(props){})React.memo为高阶组件,它与React.PureComponent非常相似,但只适用于函数组件,而不适用于class组件, 如果你的函数组件给定相同的props的情况下渲染相同的结果,那么你可以通过将其包装在React.memo中调用,以此通过记忆组件渲染结果得方式来提高组件得性能表现。这意味着在这种情况下,React将跳过渲染组件的操作并直接复用最近一次渲染的结果。 React.memo仅检查props变更。如果函数组件被React.memo包裹,且其实现中拥有useState和useContext的Hook,当context发生变化时,它仍然会重新渲染。 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。
function MyComponent(props){}
function areEqual(prevProps,nextProps){
/*
如果把nextProps传入render方法得返回结果与将nextProps传入render方法返回结果返回一致则返回true,
否则返回 false
*/
}
export default React.mome(MyComponent,areEqual)此方法仅作为性能优化的方式而存在。但请不要依赖它来组织渲染,因为这会产生bug。
注意:与class组件中
shouldComponentUpdate方法不同的是,如果props相等,areEqual会返回true;如果不相等,则返回false。这与shouldComponentUpdate方法的返回值相反。
createElement()
React.createElement(
type,
[props],
[...children]
)创建并返回指定类型得新React元素。其中的类型参数既可以是标签名字符串(如果div和span),也可以是React组件类型(class组件或函数组件),或是React Fragment类型。 使用JSX编写的代码将会转换成使用React.createElement()的形式。如果使用jsx方式,那么一般来说就不需要直接调用React.createElement()。请查阅不使用jsx。
cloneElement
React.cloneElement({
element,
[props],
[...children]
})以element元素为样板克隆并返回新的React元素。返回元素的props是将新的props与原始元素的props浅层合并后的结果。新的子元素将取代现有的子元素,而来自原始的元素的key和ref将被保留。 React.cloneElement几乎等同于:
<element.type {...element.props} {...props}>
{children}
</element.type>但是,这也保留了组件的ref。这意味着当通过ref获取子节点时,你将不会意外地从你祖先节点上窃取它。相同地ref将添加到克隆后地新元素中。 引入此API是为了替换已经弃用地React.addons.cloneWithProps()。
createFactory()
React.createFactory(type)返回用于生成指定类型地React元素得函数。与React.createElement相似地是。类型参数既可以是标签名字符串。也可以是React组件类型,或是React Fragment类型。 此辅助函数已废弃,建议使用JSX或直接调用React.createElement来代替它。 如果你使用JSX,通常不会直接调用React.createFactory。
isValidElement()
React.isValidElement(object)验证对象是否为React元素,返回值为true或者false。
React.Children
React.Children提供了用于处理this.props.children不透明数据结构地实用方法。
React.Children.map
React.Children.map(children,function[(thisArg)])在children里每个直接子节点上调用一个函数,并将this设置为thisArg。如果children是一个数组。它将被遍历并为数组中地每个子节点调用该函数。如果子节点为null或是undefined,则此方法将返回null或者undefined,而不会返回数组。
注意:如果children是一个Fragment对象,它将被视为了一个单一节点地情况处理,而不会被遍历。
React.Children.forEach
React.Children.forEach(children,function[(thisArg)])与React.Children.map()类似,但它不会返回一个数组。
React.Children.count
React.Children.count(children)返回children中组件的总数量,等同于通过map或forEach调用回调函数的次数。
React.Children.only
React.Children.only(children)验证children是否只有一个子节点(一个React元素),如果有则返回它,否则此方法会抛出错误。
React.Children.toArray
React.Children.toArray(children)将children这个复杂的数据结构以数组的方式扁平开并返回,并为每个子节点分配一个key。当你想要在渲染函数中操作子节点的集合时,他会非常实用,特别是当你想要在向下传递this.props.children之前对内容重新排序或获取子集时。
React.Fragment
React.Fragment组件能够在不额外创建DOM元素的情况下,让render方法中返回多个元素。
render(){
return (
<React.Fragment>
Some text.
<h2>A heading</h2>
</React.Fragment>
)
}你也可以实用其简写的语法<>< />。
React.createRef
React.createRef创建一个能够通过ref属性附加到React元素的ref。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
render() {
return <input type="text" ref={this.inputRef} />;
}
componentDidMount() {
this.inputRef.current.focus();
}
}React.forwardRef
React.forwardRef会创建一个React组件,这个组件能够将其接收的ref属性转发到其组件树下的另一个组件中。这种技术并不常见,但是以下两种场景中也别有用:
- 转发refs到DOM组件
- 在高级组件中转发refs
React.forwardRef接收渲染函数作为参数。React将使用props和ref作为参数来调用此函数。此函数应返回React节点。
const FancyButton = React.forwardRef((props,ref)=>(
<button ref={ref} className="FancyButton">
{props.children}
</button>
))
const ref = React.createRef();
<FancyButton ref={ref}>click me!</FancyButton>在上述的示例中,React会将<FancyButton ref={ref}>元素的ref作为第二个参数传递给React.forwardRef函数中的渲染函数。该渲染函数会将ref传递给<button ref={ref}>元素。 因此,当React附加了ref属性之后,ref.current将直接指向<button>DOM元素实例。
React.lazy
React.lazy允许你定义一个动态加载的组件。这有助于缩减bundle的体积,并延迟加载在初次渲染时未用到的组件。 你可以在代码分割文档中学习如何使用它。
const SomeComponent = React.lazy(()=>import('./SomeComponent'));请注意,渲染lazy组件依赖该组件渲染树上层的<React.Suspense>组件。这是指定加载指示器的方式。
注意:使用
React.lazy的动态引入特性需要js环境支持Promise。在IE11及以下版本的浏览器中需要引入polyfill来使用该特性。
React.Suspense
React.Suspense可以指定加载指示器(loading indicator),以防其组件树中的某些子组件尚未具备渲染条件。目前,懒加载组件是<React.Suspense>支持的唯一用例:
// 该组件是动态加载的
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// 显示 <Spinner> 组件直至 OtherComponent 加载完成
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}它已经被收录在我们的代码分割指南中。请注意,lazy组件可以位于Suspense组件树的深处 ———— 它不必包装树中的每一个延迟加载组件。最佳实践是将<Suspense>置于你想展示加载指示器的位置,而lazy()则可以被放置于任何你想要做代码分割的地方。 虽然目前尚未支持其他特性,但是未来我们计划让Suspense支持包括数据获取在内的更多场景。
