博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何用 Hooks 来实现 React Class Component 写法?
阅读量:4083 次
发布时间:2019-05-25

本文共 7073 字,大约阅读时间需要 23 分钟。

Hooks 的 API 可以参照 React 官网。本文主要是结合 Demo 详细讲解如何用 Hooks 来实现 React Class Component 写法,让大家更深的理解 Hooks 的机制并且更快的入门。注意:Rax 的写法和 React 是一致的,本文 Demo 基于 React 实现

本文内容包括如下: 一、在 Hooks 中如何实现 Class Component 生命周期 二、在 Hooks 中如何实现 shouldComponentUpdate 三、在 Hooks 中如何实现 this 四、在 Hooks 中如何获取上一次值 五、在 Hooks 中如何实现父组件调用子组件方法 六、在 Hooks 中如何获取父组件获取子组件的 dom 节点

一、在 Hooks 中如何实现 Class Component 生命周期

Hooks 的出现其实在弱化生命周期的概念,官网也讲解了原先的生命周期在写法上有哪些弊端,这里不做优缺点的比较,只给大家做写法转换。

Hooks 生命周期主要是借助 useEffectuseState 来实现,请看如下 Demo

1.1、constructor

Class Component constructor 函数只会在组件实例化时调用一次,而且会在所有生命周期函数调用之前调用

useState 传入初始化函数 fn 只会执行一次,并且执行时机在 render 之前

function useConstruct(fn) {  useState(fn);}复制代码

1.2、componentDidMount

依赖项给空数组,只会执行一次

// componentDidMountfunction useDidMount(fn) {  useEffect(fn, []);}复制代码

1.3、componentDidUpdate

依赖项不传值,任何触发的 render 都会执行

// componentDidUpdatefunction useDidUpdate(fn) {  useEffect(fn);}复制代码

1.4、componentWillUnmount

// componentWillUnmountfunction useUnMount(fn) {  useEffect(() => fn, []);}复制代码

生命周期详细 Demo 如下

import React, { useState, useEffect, useRef } from 'react';// constructfunction useConstruct(fn) {  // useState 传入初始化函数 fn 只会执行一次  useState(fn);}// componentDidMountfunction useDidMount(fn) {  // 依赖项给空数组,只会执行一次  useEffect(fn, []);}// componentDidUpdatefunction useDidUpdate(fn) {  // 依赖项不传值,任何触发的 render 都会执行  useEffect(fn);}// componentWillUnmountfunction useUnMount(fn) {  useEffect(() => fn, []);}function Block() {  const [count, setCount] = useState(0);  const instance = useRef({});  useConstruct(() => {    instance.current.name = 1;    console.log('Block Component----Construct');  });  useDidMount(() => {    console.log('Block Component----componentDidMount');  });  useDidUpdate(() => {    console.log('instance.current.name', instance.current.name);    console.log('Block Component----componentDidUpdate');  });  useUnMount(() => {    console.log('Block Component----componentWillUnmount');  });  console.log('Block render');  return (    

Block组件

count: {count}

);}export default function ParentComp() { const [unMountBlock, setUnMountBlock] = useState(false); return (

unMountBlock: {unMountBlock?'true':'false'}

{!unMountBlock ?
: null}
);}复制代码

二、在 Hooks 中如何实现 shouldComponentUpdate

通过 useMemo 来实现 shouldComponentUpdate,依赖项填写当前组件依赖的 props,useMemo内部对依赖项进行浅比较,其中的任何一个依赖项变化时,重新 render 组件。 与 Class Component 不同的是,比较操作在组件外部。

import React, { useState, useMemo } from 'react';function Counter(props) {  console.log('Counter render');  return (    

count: {props.count}

);}function Time(props) { console.log('Time render'); return (

time: {props.time}

);}export default function Demo() { const [count, setCount] = useState(0); const [time, setTime] = useState(0); const [count2, setCount2] = useState(10); // 用于实现 shouldComponentUpdate // 与 Class Component 不同点:当前是在组件外做比较 const child1 = useMemo(() =>
, [count]); const child2 = useMemo(() => , [time]); return (

count: {count}

time: {time}

count2: {count2}

{child1} {child2}
);}复制代码

三、在 Hooks 中如何实现 this

首先你要明白 Hooks 实际上仍然是 Function Component 类型,它是没有类似于 Class Component 的 this 实例的。

通过使用 useRef 来模拟实现,internalRef.current 可以认为是当前的 this 变量,用来绑定相关变量

import React, { useEffect, useRef } from 'react';export default function useThis() {  // internalRef.current 默认值为 {}  const internalRef = useRef({});  // internalRef.current 类似于 this 变量  const self = internalRef.current;  if (self.didMount) {    console.log('componentDidMount', self.didMount);  }  useEffect(() => {    self.didMount = true;  }, []);  return (    

如何使用this 变量

);}复制代码

四、在 Hooks 中如何获取上一次值

借助 useEffectuseRef 的能力来保存上一次值

import React, { useState, useRef, useEffect } from 'react';function usePrevious(value) {  const ref = useRef();  useEffect(() => {    ref.current = value;  });  return ref.current;}export default function Counter() {  const [count, setCount] = useState(0);  const previousCount = usePrevious(count);  return (    

count: {count}

previousCount: {previousCount}

);}复制代码

五、在 Hooks 中如何实现父组件调用子组件方法

上节已经说到,Hooks 实际上仍然是 Function Component 类型,它本身是不能通过使用 ref 来获取组件实例的,所以在 Hooks 中想要实现 父组件调用子组件的方法,需要两个 API来配合使用,即forwardRefuseImperativeHandle。在子组件中使用 useImperativeHandle 来导出方法,并使用 forwardRef 包裹组件, 在父组件中使用 useRef传递 ref 给子组件。

import React, { useRef, useImperativeHandle, forwardRef } from 'react';const TextInput = forwardRef((props, ref) => {  const inputRef = useRef(null);  const handleFocus = () => {    inputRef.current.focus();  };  // 暴露方法给外部组件调用  // useImperativeHandle 应当与 forwardRef 一起使用  useImperativeHandle(ref, () => ({    focusInput: handleFocus,    hello: ()=>{}  }));  return (    
);});export default function Parent() { const inputRef = useRef(null); const handleFocus = () => { console.log(typeof findDOMNode) console.log(inputRef.current) // 调用子组件方法 inputRef.current.focusInput(); }; return (
);}复制代码

六、在 Hooks 中如何获取父组件获取子组件的 dom 节点

findDOMNode 用于找到组件的dom节点,用于相关的 dom 处理操作。

import React, { useRef, useImperativeHandle, forwardRef } from 'react';import {findDOMNode} from 'react-dom';const TextInput = forwardRef((props, ref) => {  return (    
);});export default function Parent() { const inputRef = useRef(null); const handleFindDom = () => { const node = findDOMNode(inputRef.current); }; return (
);}复制代码

这里可能有人会提出疑问,在 Class Component 里面 ref 可以取到组件 dom 的同时,也可以取到组件实例方法,为何这里要拆分成 三、四 两个章节来讲? 很遗憾,在 Hooks 里面无法通过一个 ref 同时实现两个功能,只能通过规范的方式来使用,比如:

import React, { useRef, useImperativeHandle, forwardRef } from 'react';import {findDOMNode} from 'react-dom';const TextInput = forwardRef((props, ref) => {  const inputRef = useRef(null);  const compRef = useRef(null);  const handleFocus = () => {    inputRef.current.focus();  };  useImperativeHandle(ref, () => ({    // 导出方法    focusInput: handleFocus,    // 导出当前 dom 节点    compRef: compRef  }));    return (    
);});export default function Parent() { const inputRef = useRef(null); const handleFocus = () => { // 获取 TextInput 组件的 dom 节点 const node = findDOMNode(inputRef.current.compRef.current); console.log(node); // 调用 TextInput 组件方法 inputRef.current.focusInput(); }; return (
);}

作者:JSCON简时空
链接:https://juejin.im/post/5daece165188256b030ad79e
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的文章
Flutter key
查看>>
Flutter 组件通信(父子、兄弟)
查看>>
Flutter Animation动画
查看>>
Flutter 全局监听路由堆栈变化
查看>>
Flutter学习之插件开发、自定义字体、国际化
查看>>
Android 混合Flutter之产物集成方式
查看>>
Flutter混合开发二-FlutterBoost使用介绍
查看>>
Flutter 混合开发框架模式探索
查看>>
Flutter 核心原理与混合开发模式
查看>>
Flutter Boost的router管理
查看>>
Android Flutter混合编译
查看>>
微信小程序 Audio API
查看>>
[React Native]react-native-scrollable-tab-view(进阶篇)
查看>>
Vue全家桶+Mint-Ui打造高仿QQMusic,搭配详细说明
查看>>
React Native for Android 发布独立的安装包
查看>>
React Native应用部署/热更新-CodePush最新集成总结(新)
查看>>
react-native-wechat
查看>>
基于云信的react-native聊天系统
查看>>
网易云音乐移动客户端Vue.js
查看>>
JavaScript异步函数
查看>>