React
虽然平时我们都喜欢说我们用
React
作为我们的核心框架,但其实大部分人都不知道React
到底是个什么东东。事实上自从Facebook把React
和ReactDOM
分包发布之后,React
就不仅仅是一开始的前端框架了,如果在15版本之后去看一下react
和react-dom
的源码大小,你就会发现,react
仅仅1000多行代码,而react-dom
却将近2w行。是的你没看错,而且你很可能也没有想错,其实大部分的框架逻辑都在react-dom
当中,那么react
到底是个什么东东呢?
关于版本,本书是在React16+的基础上写的,React16相较于之前的版本是核心上的一次重写,虽然主要的API都没有变化,但是增加了很多能力。并且首次引入了Fiber
的概念,之后新的功能都是围绕Fiber
进行实现,比如AsyncMode
,Profiler
等。
这里并不会讲16版本之前的实现,一是面向未来,二是之前版本的源码我也没看过。
我们来看一下React暴露出来的API
const React = {
Children: {
map,
forEach,
count,
toArray,
only,
},
createRef,
Component,
PureComponent,
createContext,
forwardRef,
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
createElement: __DEV__ ? createElementWithValidation : createElement,
cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
isValidElement: isValidElement,
version: ReactVersion,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
};
请先无视__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
Children
这个对象提供了一堆帮你处理props.children
的方法,因为children
是一个类似数组但是不是数组的数据结构,如果你要对其进行处理可以用React.Children
外挂的方法。
createRef
新的ref
用法,React即将抛弃<div ref="myDiv" />
这种string ref
的用法,将来你只能使用两种方式来使用ref
class App extends React.Component{
constructor() {
this.ref = React.createRef()
}
render() {
return <div ref={this.ref} />
// or
return <div ref={(node) => this.funRef = node} />
}
}
Component & PureComponent
这两个类基本相同,唯一的区别是PureComponent
的原型上多了一个标识
if (ctor.prototype && ctor.prototype.isPureReactComponent) {
return (
!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
);
}
这是检查组件是否需要更新的一个判断,ctor
就是你声明的继承自Component or PureComponent
的类,他会判断你是否继承自PureComponent
,如果是的话就shallowEqual
比较state
和props
。
顺便说一下:React中对比一个ClassComponent是否需要更新,只有两个地方。一是看有没有shouldComponentUpdate
方法,二就是这里的PureComponent
判断
createContext
createContext
是官方定稿的context
方案,在这之前我们一直在用的老的context API
都是React不推荐的API,现在新的API释出,官方也已经确定在17大版本会把老API
去除。
新API的使用方法:
const { Provider, Consumer } = React.createContext('defaultValue')
const ProviderComp = (props) => (
<Provider value={'realValue'}>
{props.children}
</Provider>
)
const ConsumerComp = () => (
<Consumer>
{(value) => <p>{value}</p>}
</Consumber>
)
后面讲context
会专门比较新老的API的差异,提前说一句,老API的性能不是一般的差
forwardRef
forwardRef
是用来解决HOC组件传递ref
的问题的,所谓HOC就是Higher Order Component
,比如使用redux
的时候,我们用connect
来给组件绑定需要的state,这其中其实就是给我们的组件在外部包了一层组件,然后通过...props
的方式把外部的props
传入到实际组件。forwardRef
的使用方法如下:
const TargetComponent = React.forwardRef((props, ref) => (
<TargetComponent ref={ref} />
))
这也是为什么要提供createRef
作为新的ref
使用方法的原因,如果用string ref
就没法当作参数传递了。
这里只是简单说一下使用方法,后面讲ref
的时候会详细分析。
类型
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
这四个都是React提供的组件,但他们呢其实都只是占位符,都是一个Symbol
,在React实际检测到他们的时候会做一些特殊的处理,比如StrictMode
和AsyncMode
会让他们的子节点对应的Fiber的mode
都变成和他们一样的mode
createElement & cloneElement & createFactory & isValidElement
createElement
可谓是React中最重要的API了,他是用来创建ReactElement
的,但是很多同学却从没见过也没用过,这是为啥呢?因为你用了JSX,JSX并不是标准的js,所以要经过编译才能变成可运行的js,而编译之后,createElement
就出现了:
// jsx
<div id="app">content</div>
// js
React.createElement('div', { id: 'app' }, 'content')
cloneElement
就很明显了,是用来克隆一个ReactElement
的
createFactory
是用来创建专门用来创建某一类ReactElement
的工厂的,
export function createFactory(type) {
const factory = createElement.bind(null, type);
factory.type = type;
return factory;
}
他其实就是绑定了第一个参数的createElement
,一般我们用JSX进行编程的时候不会用到这个API
isValidElement
顾名思义就是用来验证是否是一个ReactElement
的,基本也用不太到
results matching ""
No results matching ""
扫码添加Jokcy,更多更新更优质的前端学习内容不断更新中,期待与你一起成长!