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>
)
}