啥是Hooks?为啥要用Hooks?Hooks该怎么用?像是Vue中的什么?React Hooks的使用姿势(上)

Hi!这里是在学习React的JustHappy,相信你和我一样,对React的Hooks早有耳闻,可以说Hooks的出现使得React的编写方式有了革命性的飞跃,更加接近原生JS、更加灵活、复用性更高......所以话不多说,我们开始吧!

同样我们也会对比着Vue去讲,一共要聊8个常用的Hooks,本篇我们先聊4个吧

什么是Hooks?为什么需要Hooks

React Hooks 是 React 16.8 版本引入的一种特性,它允许你在函数组件中使用状态和其他 React 特性,而无需将其转换为类组件。在这之前React主流的组件编写方式是类组件而不是函数式组件,

常用Hook怎么用?

当你需要定义一个响应式数据 ------ useState

首先我们明确一个基本概念!在 Web 开发中,什么是响应式数据(Reactive Data)?

只有一句话,视图层(DOM / UI)会随着状态的变化自动更新。

Vue和React中是如何使用的?

在Vue中当你需要定义一个响应式数据的时候,我们通常会想到ref或者reactive,如果我们在Vue的template中去写一个数据,并希望这个数据变化的时候在渲染层去更新这个数据,那使用ref或者reactive简直是无脑的操作,就像下面这样。

html 复制代码
<template>
  <div>
    <p>点击了 {{ count }} 次</p>
    <button @click="count++">点击</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

那么?在react中我们该怎么做呢? 那就是使用useState,同样的操作会像下面这样

js 复制代码
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>点击了 {count} 次</p>
      <button onClick={() => setCount(count + 1)}>点击</button>
    </div>
  );
}

当你需要有个"副作用" ------ useEffect / useLayoutEffect

所谓"副作用",就是副带的作用,比如说吃地瓜多的副作用是会放屁,当然副作用不一定是坏的是吧🤪🤪

在 Vue 里面,其实副作用我们也经常在搞,比如:

  • mounted 里面去请求接口;
  • watch 里监听某个变量变化后做点事情;
  • updated 里拿到更新后的 DOM 节点去干点什么;

而到了 React 里,就把这些副作用统一通过 useEffect(或者更极端一点,用 useLayoutEffect)来处理了。

你可以简单理解成,Vue 把副作用分散在生命周期和一些API里,React 则用一个钩子一把梭,收敛起来统一管理。

我们直接看看基本的代码使用吧

这是Vue中使用生命周期函数和watch实现的

html 复制代码
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="count++">+1</button>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';

const count = ref(0);

onMounted(() => {
  console.log('组件挂载了,count 是', count.value);
});

watch(count, (newVal, oldVal) => {
  console.log('count 变化了:', oldVal, '=>', newVal);
});
</script>

这是React中使用useEffect实现的

jsx 复制代码
import { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('组件挂载了,count 是', count);

    return () => {
      console.log('组件卸载或副作用清理');
    };
  }, []); // 空依赖数组,挂载时执行一次

  useEffect(() => {
    console.log('count 变化了:', count);
  }, [count]); // 依赖 count,每次 count 变化都会执行

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default Counter;

useEffect 和 useLayoutEffect 有什么区别呢?

其实他们在作用原理上只有一处不同,就是"副作用"执行的时机

  • useEffect:在浏览器完成布局与绘制之后才执行副作用函数(这个过程是不阻塞页面渲染的)

  • useLayoutEffect:在DOM变更后,浏览器绘制之前同步执行副作用函数(这个过程是阻塞渲染的)

关于这个我们也可以回顾一下Vue的生命周期,但是其边界还是有所差别

React useEffect 🆚 Vue mounted

其执行的时机是相同的,页面已经渲染,适合执行异步副作用,不影响用户看到的页面内容。

React useLayoutEffect 🆚 Vue mounted

useLayoutEffect中副作用执行的时机是对应 Vue中 mounted 之后,DOM已经被插入,但是未被渲染这一阶段,所以说useLayoutEffect同步执行副作用函数这个过程是阻塞渲染的

当你要获取一个DOM元素并对它进行....... ------ useRef

这里就非常简单了,这个操作的逻辑基本上和Vue中使用ref获取DOM一样,我们直接来看代码吧,我相信你也可以看得懂

  • Vue中
html 复制代码
<template>
  <div>
    <input ref="inputRef" placeholder="输入点啥..." />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const inputRef = ref(null)

const focusInput = () => {
  inputRef.value.focus()
}
</script>
  • React中
javascript 复制代码
import { useRef } from 'react'

export default function App() {
  const inputRef = useRef(null)

  const focusInput = () => {
    inputRef.current.focus()
  }

  return (
    <div>
      <input ref={inputRef} placeholder="输入点啥..." />
      <button onClick={focusInput}>聚焦输入框</button>
    </div>
  )
}
相关推荐
brzhang3 分钟前
代码即图表:dbdiagram.io让数据库建模变得简单高效
前端·后端·架构
SummerGao.15 分钟前
【解决】layui layer的提示框,弹出框一闪而过的问题
前端·layui
天天扭码43 分钟前
从数组到对象:JavaScript 遍历语法全解析(ES5 到 ES6 + 超详细指南)
前端·javascript·面试
拉不动的猪44 分钟前
前端开发中常见的数据结构优化问题
前端·javascript·面试
街尾杂货店&1 小时前
css word
前端·css
Мартин.1 小时前
[Meachines] [Hard] CrimeStoppers LFI+ZIP-Shell+Firefox-Dec+DLINK+rootme-0.5
前端·firefox
冰镇生鲜1 小时前
快速静态界面 MDC规则约束 示范
前端
技术与健康1 小时前
【解读】Chrome 浏览器实验性功能全景
前端·chrome
Bald Monkey1 小时前
【Element Plus】解决移动设备使用 el-menu 和 el-sub-menu 时,子菜单需要点击两次才会隐藏的问题
前端·elementui·vue·element plus
小小小小宇1 小时前
PC和WebView白屏检测
前端