React业务实战(持续补充)

390 阅读5分钟

React概览

认识

  • MVC框架;
  • 浏览器端/服务器端均可运行;
  • ReactDom.render()将模板转为HTML渲染,并插入指定DOM;
  • JSX语法;
  • 分为组件类(有状态组件)和函数组件(无状态组件)两种写法;

有状态组件与无状态组件

  • 有状态组件:继承自Component类;可以使用stateprops,并可以使用this来调用this.statethis.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 插入文档以后,才能使用这个属性,否则会报错。

 生命周期(有状态组件)

  • 三种生命周期:MountingUpdatingUnmounting;每个生命周期提供两个处理函数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:共享状态钩子

  • 多组件之间共享状态
  • 用法useContextcreateContext结合使用;
  • 状态值的改变会触发重新渲染

useReducer:状态管理钩子

  • React本身不提供状态管理功能,通常需要使用外部库,如:Redux

  • Redux 的核心概念是,组件发出 action 与状态管理器通信。状态管理器收到 action 以后,使用 Reducer 函数算出新的状态,Reducer 函数的形式是(state, action) => newStateuseReducers()钩子用来引入 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地址:

github.com/CYLpursuit/…

参考资源:
www.ruanyifeng.com/blog/2016/0…

www.ruanyifeng.com/blog/2020/0…

www.ruanyifeng.com/blog/2019/0…

zhuanlan.zhihu.com/p/63385235