一、基础hook
1、useState
// defaultValue 默认值 // 使用数组方便命名结构 const [value,setValue] = useState(defaultValue); // 初始化执行后 value的值 只能通过setValue改变 通过传递props是无法改变的 // value如果是父组件传递进来的化 只在初次渲染会复制 后续触发的更新不能修改value值 // 也就是说value值只能通过setValue修改 父组件改变props.value触发的更新不会更新value值 const [value,setValue] = useState(props.value);
2、useEffect
// 完成副作用操作 类似类组件的生命周期钩子 用于改变DOM,添加订阅,定时器等等操作 // 该函数会在组件渲染到页面后执行 // 接收一个函数和一个数组作为参数(函数可返回一个函数,用于清除计时器、等于等) // 数组是条件执行依赖,当依赖变更后会重新执行 useEffect(()=>{}, [])
3、useContext
// 主要用于数据共享,共享数据不需要通过父组件层层传递给子组件 // 接收一个React.createContext创建的值 // 该对象有俩个属性Provider Consumer 生产者 消费者 const UserInfoContext = React.createContext({}); // userlist组件 均可以获取到value传递的值 不用特意去给这些组件传递props const UserList0 = ()=> { const { username } = useContext(UserInfoContext) return <span>{username}</span> } const UserList1 = ()=> { const { username } = useContext(UserInfoContext) return <span>{username}</span> } const UserList2= ()=> { const { username } = useContext(UserInfoContext) return <span>{username}</span> } <UserInfoContext.Provider value={{username: 'admin'}}> <UserList0 /> <UserList1 /> <UserList2 /> </UserInfoContext.Provider>
二、额外hook
1、useReducer
// useState 的替代方案 // 使用方式和redux类型 // 接收参数会reducer、state、init // init: 函数类型 惰性初始化 可以将state的处理放在reducer 外部,方便重置state和action const state = 'name'; const init = (state )=> { return { name: state } } const reducer = (state, action)=> { switch(action.type) { ... } } const [value, dispatch] = useReducer(reducer, state, init);
2、useCallback
// 参数是一个函数和一个数组依赖 // 只有等依赖变更时才会执行,返回值是一个函数,如果依赖未改变返回的是缓存的函数 // 主要用于父组件传递给子组件函数类型时 避免子组件做不必要的渲染 // InputNum 在父组件num更新时,不再更新 const InputNum = memo((props: any) => { const {onChange} = props; console.log(5) return <input type="text" onChange={onChange}/> }) const App = ()=> { const [num, setNum] = useState(0); const [text, setText] = useState('0'); const onChange = useCallback((e: any)=> { setText(e.target.value); }, []); return ( <BasicContents> <span>num:{num}</span><br/> <span>text:{text}</span><br/> <InputNum onChange={onChange}/><br/> <button onClick={() => { setNum(num + 1) }}>更新 </button> </BasicContents> ) }
3、useMemo
// 接收一个函数 和一个数组依赖做完参数 和useEffect一样 // 主要用于性能优化的 因为函数组件没有shouldComponentUpdate和PureComponent // 在父组件更新时 必然会更新子组件 如果子组件有一些较大的开销(循环等) 容易有性能问题 // useMemo 仅在依赖变更时 才会执行函数,从新计算, 否则返回缓存的值 const Sum = (props:any)=> { const num = props.num; const sum = useMemo(()=> { let _sum = 0; for(let i = 0; i< num; i ++) { _sum ++; } return _sum }, [num]); return <span>{sum}</span> } const App = ()=> { const [num, setNum] = useState(10); return ( <Sum num={num} /> ) }
4、useImperativeHandle
// 主要是子组件暴露ref的实例给父组件 一般配合forwardRef使用 // forwardRef 使父组件可以拿到子组件的实例 const FancyButton = React.forwardRef((props: any, ref: any) => ( <Button ref={ref} type="primary" htmlType="submit"> {props.children} </Button> )); // bthRef 可以拿到Button的实例 <FancyButton ref={bthRef} onClick={onOk}>确定</FancyButton>; // useImperativeHandle 自定义暴露给父组件的实例属性(click) const FancyButton = React.forwardRef((props: any, ref: any) => { useImperativeHandle(ref, () => ({ click: () => { ref.current.click(); } })); return <Button ref={ref} type="primary" htmlType="submit"> {props.children} </Button> });
5、useLayoutEffect
// 作用类似useEffect 但是执行的时机不同,它是在dom变更之前,渲染的时候同步执行的 // 一般是避免视觉上不一致才会用到 useLayoutEffect(()=>{}, [])
6、useDebugValue
// 用于在 React 开发者工具中显示自定义 hook 的标签。
7、自定义hook
// 命名规范以use开头 // 属于功能抽象 跟高阶组件作用一样 // 例子:定义一个获取鼠标点击的hook const useKeyDown = () => { const [key, setKey] = useState(null); useEffect(() => { const _keydown = (e: any) => { setKey(e.code); }; document.addEventListener('keydown', _keydown); return () => { document.removeEventListener('keydown', _keydown) } }, []); return key } // 使用方式 const App = ()=> { const key = useKeyDown(); return ( <div>{key}</div> ) }
二、类组件生命周期
- 挂载(mount)
componentWillMount 组件即将挂载
componentDidMount 组件挂载完成
componentWillUnmount 组件销毁
- 更新(upData)
componentWillReceiveProps props改变
shouldComponentUpdate 是否更改state
componentWillUpdate 状态即将更新
render 渲染
componentDidUpdate 更新完成
四、函数组件和类组件的区别
函数组件没有状态,只能访问props参数,无副作用
组件不会被实例化,会提高渲染性能
没有生命周期,不能访问this
五、虚拟dom、diff、fiber、key等知识点
- 虚拟dom
模拟真实dom的一个js对象树。是为了同一计算所有的变换后,一个更新dom。尽量减少对dom的操作。
- diff
将虚拟dom转换成真实dom树的最少操作的实现就是diff算法。
tree diff:不跨层级进行移动操作,只对同一节点下的子节点进行比较。
component diff:拥有相同类的俩个组件生成相似的树形结构,拥有不同类的俩个组件生成不同的树形结构。
element diff:对于同一层级的节点,通过唯一id区分(key)
- fiber
解决组件渲染过程中的同步阻塞问题而做的任务分割,主要是通过单链表树遍历算法,可以记录遍历当下的上一步和下一步,使遍历可以暂停。
使用requestIdleCallback函数,在浏览器渲染空闲时机进行diff。
- key
减少不必要的diff算法对比,主要在diff对比前做一个校验,通过key来判断组件是否存在,是需要更新、销毁、新建等操作,提供diff算法的性能。
react中hooks、diff等知识点总结
最新推荐文章于 2024-03-19 15:20:41 发布