响应式
虚拟DOM
组件化
生命周期
数据管理和传递
数据状态管理
hooks 相关
React 提供的核心技术
- 响应式的 UI (ui = f(data))
- 虚拟 DOM
- 组件化
响应式 UI
关与响应式,你只需要关心你要什么,并且引用相关的数据,当数据发生改变的时候,React 会自动的更新 UI。
虚拟DOM
虚拟 DOM 在用户代码和真是 DOM 之间的桥梁,数据更新,会先触发虚拟DOM 改变,在将计算好的改变,一次性提交给真实 DOM,这样做可以提升性能。
组件化
- 是完整的对数据逻辑和功能的封装
- 提高代码的维护性
生命周期
React 为类组件提供了一系列的生命周期,以方便用户在某些时候可以做一些事情。
16.0+ 版本以后,react 的整个渲染过程可以分为两个阶段:
- Render 阶段:在这个阶段执行的生命周期函数都是无副作用的纯净函数,因为这个过程可能会被暂停,终止和重新执行。
- Commit 阶段:在这个阶段,React 已经开始提交 DOM,这个阶段不会被暂停或者终止,所以可以执行一些副作用的操作。
具体解析
这里将把生命周期分为初始渲染,更新,卸载 三个阶段并且配合上 React 的两个渲染阶段进行记录。
- 初始渲染
1.1 初始化渲染 Render阶段
constructorstatic getDerivedStateFromProps(prveProps, state)render
1.2 初始化渲染 Commit 阶段
componentDidMount: 此时 DOM 已经更新,可以做一些DOM操作或者副作用操作
注意:componentWillMount 已经被冷落,新的代码中最好不要使用
- 更新
2.1 更新 Render 阶段
static getDerivedStateFromProps(prveProps, state)shouldComponentUpdate: 是否渲染的优化函数,更多参考React.PureComponent类组件 或者React.Memo函数组件render
2.2 更新 Commit 阶段
getSpanshotBeforeUpdate(props,state): 注意,这里的props还没有和this.props合并,而且访问到的是还未更新的 DOMcomponentDidUpdate
- 卸载
componentWillUnmoent: 组件卸载时执行,主要用来解除监听等。
- 额外需要关注的生命周期
componetCatchError(error, info): 用于捕获子组件在渲染过程中发生的同步任务,可以做日志记录。static getDerivedStateFromError(error): 也用来捕获错误,并且返回值会合并进state中。
注意: 只要注册了上述两者之一得组件,都可称作为错误边界,只能捕获子组件在渲染期间发生的错误,不能捕获组件自身的错误。
数据管理和传递
- 组件自身可以通过
state(类组件)或者hooks(函数组件)来维护自身的状态 - 父子组件之间可以通过
props进行数据传递,也可通过传递函数来使子组件控制父组件(违反了单向数据流,不推荐) - 无关联组件之间可以通过
Context或者状态管理库(redux,mobx等)进行数据状态管理
数据状态管理
redux:这是React应用中,使用最广范的状态管理库,有完备的中间件机制和数据状态管理机制。mobx: 这是一个后起的状态管理库,提供了简介的 API,面向对象的方式创建 Store 和 多种自由的写法。
两者的共同点和区别
共同点:
-
它们都是统一管理应用状态
-
某一状态只有一个来源(
Stroe是唯一的数据来源) -
操作更新状态的方式统一(都是通过
action去触发跟新状态) -
支持
Store和React(react-redux和react-mobx)连接,以此,通常可以把组件分为两种组件- 容器组件:负责处理业务的数据和状态,将数据和状态传递给需要显示的组件
- 展示组件:负责展示视图,将的到的数据合理的展示出来
区别:
redux的编程范式规范,需要编写一些模板代码来创建整个数据流程。mobx的没有固定的写法,相对来说比较自由,但在处理大应用时可能会有编程风格不统一的维护风险。- 异步支持方面,
redux需要redux-thunk或者redux-saga的协助才能完成异步处理,而mobx则天生支持异步处理,不需要其他的工具库支持。 - 编程风格上,
redux仅支持纯函数,要求数据不可变,而mobx支持面对对象和函数式编程,状态的修改是直接在原状态对象上修改的。 redux只支持单一store,mobx支持多store。
hooks 相关
hooks是 React 新添加的增强函数组件功能的 api。hooks只能在 React 函数组件里面使用,不能再类组件和普通 js 函数中使用。hooks只能定义在函数组件的最顶层区域,不能再条件判断,循环嵌套等会影响hooks执行顺序的语句中使用
主要 hooks 介绍
-
useState- 类似于
setState,主要是帮助函数组件获取和改变状态值 - 需要注意的是函数组件中的
state每次更新都是独立的,这种特性是由 js 中的闭包决定的。
function APP(props) { const [use, setUser] = useState('tom'); useEffect(() => { setTimeout( () => { console.log(use); // 这里的结果是 tom }, 3000 ); }, []); return ( <div onClick={() => {setUser('merry')}}></div> ) }上例中最终结果及时你点击过按钮更新了
use结果是tom。- 如果想访问上一次的 state,可以这么做
setUser(use => use + "o" );- useState 的参数就是初始化的 state 值,只会在初始化时执行一次。
- state 如果是个引用类型的值,需要每次更新时手动去合并,不然 React 会直接做覆盖。
- 类似于
-
useEffect-
这个钩子接收两个参数,第一个参数是个回调函数,第二个参数可以为空或者不传递。
import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); // 返回值告诉了 react 需要去清理哪些操作 return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } -
第二个参数如果不传递,
useEffect相当于DidMount和DidUpodate。空数组相当于DidMount。如果数组中包含state,则会在初始化和相关 state 更新时执行回调函数。 -
回调函数的返回值会在每次回调函数执行前调用,基本过程是,先清除 -> 再注册
-
-
更多的钩子函数