react conText
使用API
React.createContext
返回的是组件对象 可以利用结构的方式
- 第一种方式
使用Provider
包裹的组件都可以获取提供者的value
Context.Consumer
组件里面使用函数 函数返回一个组件 函数的参数为Context初始化的参数
- 第二种方式
- 使用
Context.Provider
包裹所有的组件 - 在子组件里面使用
static contextType = 创建的Context
则会自动向上查找 然后在组件内部可以通过this.context
获取值
Portals插槽
- 可以将一个
dom
插入到其他dom
下面ReactDOM.createPortal(需要插入的节点, 需要挂载的节点)
React.createPortal(Component, nodeElement)
HOC
- 主要存在作用 抽离
state
复用逻辑 操作方式可以直接使用ES7装饰器 - 对一个函数传入一个组件 返回一个组件 函数里面将公共的逻辑抽离出来
- 例如:每个页面都需要加载数据 渲染页面 那么就可以将公共的获取数据接口抽离出来 对指定组件进行渲染
hoc
生命周期 组件的didMount
->hocDidMount
->hocwillMount
->hocwillUnMount
->unMount
HOC都有一个通病就是props可能重复
例如:
- 每个组件都有共同的操作 比方说:
A组件
需要修改名字B组件
也需要修改名字 就可以将状态提升 利用HOC
传入修改事件以及传入的值 Loading
操作 每个组件都有一个loading
状态 利用hoc
接收一个loading
是否显示的状态 然后用这个loading
状态控制显示loading
组件还是业务组件- 数据请求 两组同样的数据请求 放在不同的展示组件里面渲染 可以将获取数据的操作抽离出来
鼠标移动例子 所有的组件都需要获取在某个组件内的鼠标移动x y
const withMouse = Component => { return class extends React.Component { state = { x: 0, y: 0 }; handleMouseMove = event => { this.setState({ x: event.clientX, y: event.clientY }); }; render() { return ( <div onMouseMove={this.handleMouseMove}> <Component {...this.props} mouse={this.state}/> </div> ); } } }
RenderProps
与HOC
惊人的相似。当是不会再出现props重复的问题。实际上就是一个回调函数 作用都是获取外部数据
// 例如 将重复的操作放在 组件内部 组件内部通过调用外部的render方法 实现将外部组件可以获取组件内部的state 从而不影响props的传递 class Mouse extends React.Component { static propTypes = { // render: required }; state = { x:0, y:0 }; handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) }; render() { return ( <div onMouseMove={this.handleMouseMove}> {this.props.render(this.state)} </div> ); } }
Refs 转发
- 主要是不方便获取叶子组件的ref 利用ref转发可以准确的获取的叶子组件的ref
const ref = React.createRef() React.forwardRef((props, ref) => { <Component ref={ref}> })
ref则会成为叶子组件的ref
Fragments
- 主要是在代码逻辑中对这些组件进行 不会产生任何的额外节点
<> <div>hello</div> </>
React.lazy React.suspense 懒加载
React.lazy(() => import('./Component'));
- 以前是
webpack
将所有打包成为一个文件 导致文件特别大 不利于代码拆分 这个时候需要代码拆分 const OtherComponent = React.lazy(() => import('./OtherComponent'));
这样导入的组件 如果有多个懒加载组件 那么展示会以加载时间最长的组件显示React.suspense
参数fallback
懒加载过程中需要展示的内容
- 原理分析
- 当父组件渲染到子组件的时候发现异步请求 直接抛出错误 捕获的结果是个
promise
ComponentDidCatch
捕获到这个promise
的异常pending
状态下渲染fallback
- 当
resolve
时重新render
遇到下一个异步请求重复上面操作 - 直到整个父组件抛出的
promise
对象都将resolve
将loading
换成真正的组件
HOOK 钩子
HOOK提供了一系列函数式组件的钩子
const [value, setValue] = useState();
value
则是state
状态 setValue
则是个函数 需要设置值直接调用setValue
传入需要设置的值即可
useEffect
传入一个匿名函数 该匿名函数的作用相当于DidMount
和DidUpdate
可以在匿名函数里面返回一个函数
Component 和 PurComponent 的区别
区别点: 前者自带通过props
和state
的浅对比来实现shouldComponentUpdate
而后者没有 只要props
变化就会重新render
- PurComponent缺点
可能因为深层数据不一致而产生错误的否定判断 从而界面得不到更新
为什么会产生:新的对象简单的引用了原始对象 改变了新的对象将影响到原始对象 如foo = {a: 1} bar = foo bar.a = 2
这个时候区对比foo
和bar
是一样的 一般解决是使用深拷贝 则可以 引用immutable
也可以优化
截流和防抖
- 截流 控制指定时间触发一次 在指定时间内调用不能超过一次
- 防抖 防抖确保函数不会在上一次调用后一定量的时间被执行
requestAnimationFrame
节流 浏览器会确保每一秒是60帧 可以防止每秒超过60帧的操作 自己限流
setState
异步处理 多次增加数据会导致数据返回不到预期 可以使用函数形式处理
为什么使用异步处理?
setState
不会立马改变React
组件和state
的值setState
通过触发一次组件的更新来引发重绘- 多次
setState
函数调用产生的效果会合并
本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。