React概览
认识
- MVC框架;
- 浏览器端/服务器端均可运行;
ReactDom.render()将模板转为HTML渲染,并插入指定DOM;- JSX语法;
- 分为组件类(有状态组件)和函数组件(无状态组件)两种写法;
有状态组件与无状态组件
-
有状态组件:继承自
Component类;可以使用state和props,并可以使用this来调用this.state和this.props;有生命周期函数; -
无状态组件:就是一个函数;只可以使用
props,且无需使用this;无生命周期;
JSX
-
基本语法规则:遇
<开头用HTML语法解析,遇{用JS规则解析; -
允许直接在模板中插入变量,使用
{}包裹;如果变量为数组,则会展开数组的所有成员; -
有状态组件添加组件属性可以通过
this.props对象获取,对象的属性与组件的属性一一对应;但class属性需改用className;for属性需改用
htmlFor因为class和for为JS保留字;此外,this.props.children表示组件的所有子节点,值有三种可能:如果当前组件没有子节点,它就是undefined,如果有一个子节点,数据类型是object,如果有多个子节点,数据类型就是array,所以,处理this.props.children的时候要小心,React 提供一个工具方法React.Children来处理this.props.children; -
React.Children:可以用React.Children.map来遍历子节点,而不用担心有状态组件this.props.children的数据类型是undefined还是object更多用法可参考官文; -
propTypes:组件类属性; -
获取真实的DOM节点:由于有状态组件
this.refs.[refName]属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
生命周期(有状态组件)
- 三种生命周期:
Mounting,Updating,Unmounting;每个生命周期提供两个处理函数will在进入状态之前调用,did在进入状态之后调用; - 七个事件处理函数:
componentsWillMount(),componentsDidMount(),componentsWillUpdate,componentsDidUpdate(),componentsWillUnmount();此外,还有componentWillReceiveProps()表示已加载组件收到新的参数时调用,shouldComponentUpdate()判断组件是否需要重新渲染时调用;
重点:React函数组件及其钩子
函数组件(无状态组件)
思想:组件尽量写成纯函数,如需额外功能和钩子,则使用钩子函数。
函数即组件;首字母大写;只做一件事,返回HTML代码而不做其他副效应;每渲染一次组件,函数组件都自动执行一次。
钩子
钩子也是函数;函数组件的副效应解决方案;为函数组件引入副效应;特定副效应需要特定钩子,如:useState(状态钩子),useContext(共享状态钩子),useReducer(状态管理钩子),useRef(引用钩子)等,但useEffect是通用副效应。
useEffect:副作用钩子
React框架内部提供;函数组件内部调用;组件渲染每次调用函数组件时都会执行;
-
参数:两个参数,第一个参数是副效应函数,第二个参数是数组。第二个参数使用一个数组指定副效应函数的依赖项,只有依赖项发生变化,才会重新执行;当使用空数组时,表示不依赖任何依赖项,则只有第一次页面渲染才会执行。
useEffect( () => { // 想要执行的副效应 }, []);
-
使用场景:获取数据,事件监听或订阅,修改DOM,输出日志等
-
返回值:允许返回一个函数,在组件卸载/重新执行时执行,可用于清除添加的副效应。
-
注意点:多个不相关的副效应,应该调用多个
useEffect,而不是混在一起。
useState:状态钩子
React框架内部提供;函数组件内部调用;生成一个状态变量,用于保存数据;通常每次调用set都会自动触发render函数使得组件重新渲染,但在一次useEffect调用过程中多个set也只触发一次函数组件重新渲染;
- 参数:接受状态的初始值,作为参数;
- 返回值:该函数返回一个数组,数组的第一个成员是一个变量,指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是
set前缀加上状态的变量名;
useRef:引用钩子
-
跨渲染周期,也就是在组件被多次渲染之后依旧不变的属性,适用于多次渲染仍要保持不变的变量;
-
可反映先前状态
let param = useRef('default value'); param.current = 'new value';console.log('param', param.current);
-
对它修改也不会引起组件渲染;
-
可以用于获取组件或者DOM节点;
let ele = useRef(); console.log('ele', ele.current);
//react模板中
useContext:共享状态钩子
- 多组件之间共享状态
- 用法,
useContext与createContext结合使用; - 状态值的改变会触发重新渲染
useReducer:状态管理钩子
-
React本身不提供状态管理功能,通常需要使用外部库,如:Redux; -
Redux的核心概念是,组件发出 action 与状态管理器通信。状态管理器收到action以后,使用Reducer函数算出新的状态,Reducer 函数的形式是(state, action) => newState。useReducers()钩子用来引入 Reducer 功能。 -
由于 Hooks 可以提供共享状态和
Reducer函数,所以它在这些方面可以取代Redux。但是,它没法提供中间件(middleware)和时间旅行(time travel),如果你需要这两个功能,还是要用 Redux。
useCallback
- 组件第一次渲染时执行,之后其依赖的函数发生变化时再执行
- 反映当前状态
- 缓存机制,用于性能优化
- 适用场景:依赖本地状态或props来创建函数需要缓存的情况,可避免不必要的更新
useMemo
- 组件第一次渲染时执行,之后其依赖的变量发生变化时再执行
- 反映当前状态
- 缓存机制,用于性能优化
- 适用场景:避免不必要的更新
封装自己的钩子
- 一律使用
use前缀命名;
难点:如何合理选择钩子并使用
useState or useReducer
useMemo or useCallback
React.memo() or redux
路由模块:react-router-dom
-
useHistory
const history = useHistory();
状态管理模块:react-redux
-
useDispatch
const dispatch = useDispatch();
DEMO地址:
参考资源:
www.ruanyifeng.com/blog/2016/0…
www.ruanyifeng.com/blog/2020/0…