Ashun's 技術駅 Ashun's 技術駅
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Ashun

前端界的小学生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

  • 高级指引

  • Hook

  • 案例演示

  • 商医通项目

    • react基础笔记
    • typescript笔记
    • antd基本使用
    • react项目笔记
    • 课件-react路由-V6
    • 课件-redux-toolkit
    • 课件-国际化
    • 课件-其他hooks
      • 课件-虚拟dom和diff算法
    • 《React》笔记
    • 商医通项目
    ashun
    2024-01-22
    目录

    课件-其他hooks

    # 课件-其他hooks

    # useContext

    作用:在接收context传递数据的组件中,使用useContext快速拿到数据

    -- context.js
    import React from 'react'
    export default React.createContext()
    
    -- App.jsx
    export default class App extends Component{
        render(){
            return (
            	<textContext.Provider value={{name:'zs'}}>	
                	<Test></Test>
                </textContext.Provider>
            )
        }
    }
    
    -- Test.jsx
    import React, {useContext} from 'react'
    import testContext from './content'
    export default function Test(){
        const context = useContext(testContext)
        console.log(context)
        return <div></div>
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    # useRef

    新的创建ref对象的方式

    function TextInputWithFocusButton() {
      const inputEl = useRef(); // 传入的null表示inputEl.current的初始值
      const onButtonClick = () => {
        // `current` 指向已挂载到 DOM 上的文本输入元素
        inputEl.current.focus();
      };
      return (
        <>
          <input ref={inputEl} type="text" />
          <button onClick={onButtonClick}>Focus the input</button>
        </>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    # useReducer

    组件中有大量数据,使用useState,略显繁琐,使用useReducer更方便的管理数据

    import React, { useReducer } from 'react'
    
    const initialState = { count: 0, msg: '哈哈' }
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {
            ...state,
            count: state.count + 1,
          }
        case 'decrement':
          return {
            ...state,
            count: state.count - 1,
          }
        default:
          throw new Error()
      }
    }
    export default function Test1() {
      const [state, dispatch] = useReducer(reducer, initialState)
      return (
        <>
          Count: {state.count}
          msg: {state.msg}
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
        </>
      )
    }
    
    // useReduder的第三个参数:
    
    function init(initialCount) {
      return {count: initialCount};
    }
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        case 'reset':
          return init(action.payload);
        default:
          throw new Error();
      }
    }
    
    function Counter({initialCount}) {
      const [state, dispatch] = useReducer(reducer, initialCount, init);
      return (
        <>
          Count: {state.count}
          <button
            onClick={() => dispatch({type: 'reset', payload: initialCount})}>
            Reset
          </button>
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
        </>
      );
    }
    
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67

    # useCallBack

    ​ 每次函数组件更新,函数组件内的函数会重新创建.使用useCallBack可以缓存函数

    import React, { useState, useCallback } from 'react'
    export default function Test() {
      console.log('test渲染了')
      const [count, setCount] = useState(0)
      // 如果是空数组则回调函数只创建一次.如果不写第二个参数,或第二个参数监听数据,回调函数则创建多次
      const handle = useCallback(() => {
        console.log(count)
        setCount(count + 1)
      }, [count])
      return (
        <div>
          <div>{count}</div>
          <button onClick={handle}>按钮</button>
        </div>
      )
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    # React.memo

    作用类似于类组件的PureComponent, 当父组件更新时,动态判断子组件使用更新

    PureComponent: 当自身状态数据[state]和外部数据[props]没有变化的时候,组件不重新渲染

    --App.js  
    
    import React, { useState, useEffect } from 'react'
    import Test from './Test'
    function getRandomIntInclusive(min, max) {
      min = Math.ceil(min)
      max = Math.floor(max)
      return Math.floor(Math.random() * (max - min + 1)) + min //含最大值,含最小值
    }
    class App extends React.Component {
      state = {
        count: 0,
      }
      render() {
        console.log('app渲染了')
        return (
          <div>
            <button
              onClick={() => {
                this.setState({
                  count: getRandomIntInclusive(1, 2),
                })
              }}
            >
              按钮
            </button>
            <Test count={this.state.count}></Test>
          </div>
        )
      }
    }
    
    export default App
    
    
    -- Test.js 
    import React from 'react'
    
    function Test(props) {
      console.log('Test组件渲染了-' + props.count)
      return <div>{props.count}</div>
    }
    export default React.memo(Test)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43

    # useMemo

    会缓存一个计算的结果,如果没有变化,则不会重新执行计算

    // 使用前
    import React,{useState} from 'react';
     
    export default function WithoutMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
     
        function expensive() { // expensive 昂贵的
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }
     
        return <div>
            <h4>{count}-{val}-{expensive()}</h4>
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    
    // 使用后
    export default function WithMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
        const expensive = useMemo(() => {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }, [count]);
     
        return <div>
            <h4>{count}-{expensive}</h4>
            {val}
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47

    # useImperativeHandle

    useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值. useImperativeHandle 应当与 [forwardRef]一起使用

    作用: 封装公共组件的时候,可以给使用公共组件的组件提供指定的API. 有条件的操作公共组件的真实dom

    --App.js
    import React, { useState, useEffect } from 'react'
    import FancyInput from './FancyInput'
    
    const inputRef = React.createRef()
    class App extends React.Component {
      render() {
        return (
          <div>
            <button
              onClick={() => {
                
                console.log(inputRef.current.focus())
              }}
            >
              按钮
            </button>
            <FancyInput ref={inputRef}></FancyInput>
          </div>
        )
      }
    }
    
    export default App
    
    
    --FancyInput.js
    import React, { useRef, useImperativeHandle, forwardRef } from 'react'
    function FancyInput(props, ref) {
      const inputRef = useRef()
      useImperativeHandle(ref, () => ({
        focus: () => {
            
          inputRef.current.focus()
        },
      }))
      return <input ref={inputRef} />
    }
    FancyInput = forwardRef(FancyInput)
    export default FancyInput
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    # useLayoutEffect

    作用与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

    useEffect
    这个是在render结束后,你的callback函数执行,但是不会阻塞浏览器渲染
    
    useLayoutEffect
    这个是用在处理DOM的时候,当你的useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制
    
    import React, { useEffect, useLayoutEffect, useRef } from 'react'
    import TweenMax from 'gsap' // npm i [email protected]
    import './index.css'
    
    const Animate = () => {
      const REl = useRef(null)
      useLayoutEffect(() => {
        /*下面这段代码的意思是当组件加载完成后,在0秒的时间内,将方块的横坐标位置移到600px的位置*/
        TweenMax.to(REl.current, 0, { x: 600 })
      }, [])
      return (
        <div className="animate">
          <div ref={REl} className="square">
            square
          </div>
        </div>
      )
    }
    
    export default Animate
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    # useDebugValue

    useDebugValue 可用于在 React 开发者工具中显示 自定义 hook 的标签

    注意:只能在自定义hook中使用

    
    import { useState, useDebugValue } from 'react'
    // 取 min 和 max之间的随机整数
    function getRandomIntInclusive(min, max) {
      min = Math.ceil(min)
      max = Math.floor(max)
      return Math.floor(Math.random() * (max - min + 1)) + min //含最大值,含最小值
    }
    
    export default function useFriendStatus() {// 自定义hook函数
      const [isOnline, setIsOnline] = useState(null)
    
      setTimeout(() => {
        let result = getRandomIntInclusive(0, 1)// [0 | ]
        console.log(result)
        setIsOnline(result ? 'online' : 'offline')
      }, 1000)
    
      // 在react开发者工具中的这个 Hook 旁边显示标签
      // "FriendStatus: Online"
      useDebugValue(isOnline)
    
      return isOnline
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    编辑 (opens new window)
    课件-国际化
    课件-虚拟dom和diff算法

    ← 课件-国际化 课件-虚拟dom和diff算法→

    最近更新
    01
    课件-react路由-V6
    01-22
    02
    课件-国际化
    01-22
    03
    课件-redux-toolkit
    01-22
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式