React顶层API
组件
React.Component
React.Component
是使用 ES6 classes
方式定义 React
组件的基类:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</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
创建元素
React.createElement
JSX
实际上是React.createElement
的语法糖,最终都会转换为React.createElement
函数
参考通过源码学习React.createElement
转换元素
React.Children
React.Children
提供了用于处理 this.props.children
不透明数据结构的实用方法。
我们先来看看children
上有哪些东西
import React from 'react'
class ReactChildren extends React.Component {
render () {
// children还可以是一个函数,如果内部不调用,则会报错,所以内部需要使用this.props.children()来调用
console.log(this.props.children, 'ReactChildren');
return (
<div>
{ this.props.children }
</div>
)
}
}
export default class Wrapper extends React.Component {
constructor(props) {
super(props)
this.titleRef = React.createRef();
}
handleClick = () => {
console.log('clicked!')
}
render () {
return (
<ReactChildren>
{/* 在children里传入一个函数,内部需要进行调用,否则报错,同样可以进行传参,和render props一样,只不过是写在了children里面 */}
{/* {(msg) => { return <h1>{msg}</h1> }} */}
<h1 name="name" ref={this.titleRef}>Title</h1>
<ul>
<li key="a">aaa</li>
<li key="b">bbb</li>
<li key="c">ccc</li>
</ul>
<button onClick={this.handleClick}>按钮</button>
</ReactChildren>
)
}
}
React.Children.map
React.Children.map
的实现比数组的map
实现要多,因为children
的值可能是null
,或者其他,直接使用this.props.children.map
可能会报错
React.Children.map(this.props.children, (child, index) => {console.log(child, index)})
React.Children.forEach
与 React.Children.map()
类似,但它不会返回一个数组。
React.Children.forEach(this.props.children, (child, index) => {console.log(child, index)})
React.Children.count
输出children
的长度
React.Children.count(this.props.children)
React.Children.only
验证 children
是否只有一个子节点(一个 React
元素),如果有则返回它,否则此方法会抛出错误
注意:
React.Children.only()
不接受React.Children.map()
的返回值,因为它是一个数组而并不是React
元素。
try {
console.log(React.Children.only(this.props.children))
} catch (error) {
console.log(error)
}
React.Children.toArray
将 children
这个复杂的数据结构以数组的方式扁平展开并返回,并为每个子节点分配一个 key
。当你想要在渲染函数中操作子节点的集合时,它会非常实用,特别是当你想要在向下传递 this.props.children
之前对内容重新排序或获取子集时。
React.Children.toArray(this.props.children)
以上所有的方法都不涉及子元素的情况,只能操作当前层级的元素,如果需要操作整个树,需要自己递归。
cloneElement()
cloneElement()
是createFactory()
的替代品,createFactory()
已被废弃
cloneElement()
以 element
元素为样板克隆并返回新的 React
元素。返回元素的 props
是将新的 props
与原始元素的 props
浅层合并后的结果。新的子元素将取代现有的子元素(如果子元素里有children,要记得同时传入),而来自原始元素的 key 和 ref 将被保留。
children
是只读的,我们不能直接对children
进行修改,就可以借助此api
进行修改;
{ React.Children.map(this.props.children, (child, index) => {
console.log(child);
return React.cloneElement(child, { style: { color: 'red' }, aaa: 'title' }, [...child.props.children, <span key={null}>新添加的内容</span>])
}) }
类似createElement
,第一个参数是具体React
元素,第二个参数是扩展的属性,第三个参数是子元素
扩展的属性会进行一个浅合并,相同的属性名将直接覆盖,不相同的则逐个添加到props
子元素是个数组,
- 如果不传,则里面的元素不会发生变化,有多少克隆多少
- 如果传了,则里面的元素会整体替换为传入的元素,因此如果当前元素里面仍存在
children
不想丢失,也需要进行扩展
isValidElement()
验证对象是否为 React
元素,返回值为 true
或 false
React.isValidElement(this.props.children)
有一点需要注意的是,判断的元素必须有单一根元素(Fragment也算),像上面例子那种没有单一根元素的,其实是一个数组,都会被判定为false
Fragments
React 中的一个常见模式是一个组件返回多个元素。Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
例如在特定标签中(例如table
th
td
),限定标签类型,此时如果有多个标签,给定额外的根标签会使HTML无效,Fragments就解决了此问题
可以使用<React.Fragment>
组件,或者短语发<></>
使用显式 <React.Fragment>
语法声明的片段可能具有 key
,key
是唯一可以传递给 Fragment
的属性。未来可能会添加对其他属性的支持,例如事件。
Refs
refs相关操作,查阅React ref的使用,或官方文档Refs & DOM/Refs 转发
Suspense
Suspense
用于懒加载组件时进行,React.Suspense
可以指定加载指示器(loading indicator
),以防其组件树中的某些子组件尚未具备渲染条件。目前,懒加载组件是 <React.Suspense>
支持的唯一用例
import React, { Suspense } from 'react'
const List = React.lazy(() => import('./列表渲染'))
class LazyLoadTest extends React.Component {
render () {
return (
<Suspense fallback={<div>Loading</div>}>
<List></List>
</Suspense>
)
}
}
export default LazyLoadTest
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com