缘起
在这个 find a job 地狱难度的时间,整理一份 React 核心指南,共勉之
目录结构
文章目录
壹、Context
Context
提供了一个无需为每层组件手动添加props
,就能在组件树间进行数据传递的方法。
for example
组件A —— time 数据 需要向下传递,我们可以通过 props 来传递,但是那样过于耦合
组件B
组件C
组件D
...
典型解决方案就是Context
- 创建context :
const ThemeContext = React.createContext('C_data');
hook 写法
const value = useContext(MyContext);
- API
- React.createContext
const MyContext = React.createContext(defaultValue);
- Context.Provider
<MyContext.Provider value={/* 某个值 */}>
- React.createContext
// 创建context
const DataContext = React.createContext('123');
class App extends React.Component {
render() {
return (
// 使用 Provider 将当前值传递下去
<DataContext.Provider value="abc">
<A />
</DataContext.Provider>
);
}
}
// 中间的组件再也不必指明往下传递 theme 了。
function A() {
return (
<div>
<B />
</div>
);
}
class B extends React.Component {
// 当前值为 abc
// React 会往上找到最近的 theme Provider,然后使用它的值
static contextType = DataContext;
render() {
return <p/>this.context</p>;
}
贰、Refs & DOM
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素
- 创建 Refs
React.createRef()
// hook 写法
const refContainer = useRef(initialValue);
for example
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
// 访问 ref
const node = this.myRef.current;
叁、Refs转发 forwardRef
如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用),或者可以将该组件转化为 class 组件。
有了上面 Refs 操作Dom 的认识,下面跑抛出一个问题,现在我要在父组件 <F_component />
中 获取子组件的ref
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
// 我可以在这里访问 被转发的 `button` 的`ref`
render() {
return <F_component ref={
this.ref} />;
}
}
const F_component = React.forwardRef((props, ref) => (
<button ref={
ref} className="F_component">
{
props.children}
</button>
));
// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<F_component ref={
ref}>Click me!</F_component>;
- 我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
- 我们通过指定 ref 为 JSX 属性,将其向下传递给 。
- React 传递 ref 给 forwardRef 内函数 (props, ref) =>…,作为其第二个参数。
- 我们向下转发该 ref 参数到
<button ref={ref}>
,将其指定为 JSX 属性。 - 当 ref 挂载完成,ref.current 将指向
<button>
DOM 节点。
肆、 Fragments
Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
Fragments = jsx: <> … </>
or
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
- 短语法
<></> 不支持 key
伍、高阶组件(HOC)
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
上面👆是官方短解释 以下我通俗一点解释吧:
想必大家都知道JavaScript的高阶函数吧。其实高阶组件就相当于一个高阶函数。即:高阶函数,就是函数中可以传入另一个函数作为参数的函数。
- 在React中 => JSX 函数即组件 = 高阶组件是将组件转换为另一个组并返回
for example
假设有一个组件MyComponent,需要从LocalStorage中获取数据,然后渲染数据到界面。我们可以这样写组件代码:
import React, {
Component } from 'react'
class MyComponent extends Component {
componentWillMount() {
let data = localStorage.getItem('data');
this.setState({
data});
}
render() {
return <div>{
this.state.data}</div>
}
}
- 现在我们要封装一个高阶组件
withPersistentData
来达到上述代码逻辑的复用
import React, {
Component } from 'react'
function withPersistentData(WrappedComponent, key) {
return class extends Component {
componentWillMount() {
let data = localStorage.getItem(key);
this.setState({
data});
}
render() {
// 通过{...this.props} 把传递给当前组件的属性继续传递给被包装的组件WrappedComponent
return <WrappedComponent data={
this.state.data} {
...this.props} />
}