啥是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>
  )
}
相关推荐
qq_5470261796 小时前
Flowable 工作流引擎
java·服务器·前端
刘逸潇20056 小时前
CSS基础语法
前端·css
Sheldon一蓑烟雨任平生7 小时前
Vue3 插件(可选独立模块复用)
vue.js·vue3·插件·vue3 插件·可选独立模块·插件使用方式·插件中的依赖注入
吃饺子不吃馅7 小时前
[开源] 从零到一打造在线 PPT 编辑器:React + Zustand + Zundo
前端·svg·图形学
小马哥编程8 小时前
【软考架构】案例分析-Web应用设计(应用服务器概念)
前端·架构
鱼与宇8 小时前
苍穹外卖-VUE
前端·javascript·vue.js
啃火龙果的兔子8 小时前
前端直接渲染Markdown
前端
z-robot9 小时前
Nginx 配置代理
前端
mapbar_front9 小时前
React 中 useCallback 的基本使用和原理解析
react.js
用户47949283569159 小时前
Safari 中文输入法的诡异 Bug:为什么输入 @ 会变成 @@? ## 开头 做 @ 提及功能的时候,测试同学用 Safari 测出了个奇怪的问题
前端·javascript·浏览器