彻底理清vue和react的生命周期钩子和hooks
阅读本文章大约需要10分钟,将和各位一起彻底理清vue2,vue3,react他们的生命周期和hooks之间的区别。
首先是生命周期的概念,不管vue还是react他们的每一个组件都存在几个阶段:即挂载,更新,卸载等,这些阶段的命名和定义在vue和react中略有不同,但原理是一样的。生命周期钩子就在这些阶段时被调用的函数。
而Hooks(在vue3中是Vue Composition API)。它是一系列函数,允许我们在组件里管理状态,使用其他vue和react的特性。React Hooks 和 Vue Composition API 在概念上很相似,都提供了一种函数式的方式来管理组件状态和副作用。通过Hooks,开发者可以更专注于组件的核心逻辑,使得代码更加清晰和可维护。
Vue2和Vue3: Vue的生命周期钩子更加精细,可以在更多的阶段进行操作。它的使用更为显式,每个钩子都有明确的命名和调用时机。
Vue2:
生命周期:beforeCreate,created,beforeMount,mounted,beforeUpdate, Updated,activated,deactivated,beforeDestroy,destroyed等。
你可以在每个生命周期中根据逻辑做不同的操作,这里不再累述。
Hooks:Vue2没有官方的Hooks,但是你可以使用Mixin,scoped,slots, Provide / Inject等实现类似于 Hooks 的效果,管理组件的状态和副作用。 举例:
// mixinA.js
export default {
data: function() {
return {valueA:’’}
},
methods: {
doSomeThing(){
this.valueA=’hollo world’;
return this.valueA;
}
},
};
组件中使用:
<script>
import MixinA from "./mixins/mixinA.js";
export default {
mixins: [MixinA],
data() {
return{
Name:’Tom’
}
},
methods: {
clickHandle(){
console.log(this.doSomeThing()+’ ’+this.Name);
}
}
};
</script>
Vue3:
生命周期:beforeCreate , created , beforeMount , mounted , beforeUpdate , updated , beforeUnmount , unmounted等,用于处理组件的生命周期,在组件的每个不同阶段被调用。
Hooks:
Vue3引入的新特性Vue Composition API,包括:ref , reactive , computed , watch , provide 和 inject , onBeforeMount, onMounted, onBeforeUpdate, onUpdated,onBeforeUnmount,onUnmounted等。
举例:创建自定义Hook,我们通过onMounted生命周期钩子,在组件挂载后自动发起请求。
*// useFetch.js*
import { ref, onMounted } from 'vue';
import axios from 'axios';
export function **useFetch**(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
async function **fetchData**() {
try {
const response = await axios.get(url);
data.value = response.data;
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
onMounted(fetchData);
return { data, error, loading };
}
在组件中使用自定义Hook
<template>
<div>
<h2>用户列表</h2>
<div v-if="loading">加载中...</div>
<ul v-if="data">
<li v-for="user in data.users" :key="user.id">{{ user.name }}</li>
</ul>
<div v-if="error">{{ error.message }}</div>
</div>
</template>
<script>
import { defineComponent } from 'vue';
import { useFetch } from './useFetch';
export default defineComponent({
setup() {
const { data, error, loading } = useFetch('https://api.example.com/users');
return { data, error, loading };
},
});
</script>
通过import导入useFetch,并在setup()函数中调用它,即在组件挂载后自动发起请求'api.example.com/users'。
React:
React 16 之前有三个生命周期阶段:挂载、更新和卸载。React 16 之后引入了新的生命周期方法。
1. 挂载阶段:
constructor: 构造函数,在组件创建时调用。
componentWillMount (React 16 之前): 在组件即将被挂载到页面上时调用。
render: 渲染函数,在此函数中返回组件的虚拟 DOM。
componentDidMount: 组件已经被挂载到页面上后调用。
2. 更新阶段:
componentWillReceiveProps (React 16 之前): 在组件接收到新的 props 之前调用。
shouldComponentUpdate: 在组件接收到新的 props 或者 state 时调用,用于判断是否重新渲染组件。
componentWillUpdate (React 16 之前): 在组件即将更新时调用。
render: 同上。
componentDidUpdate: 组件更新完成后调用。
3. 卸载阶段:
componentWillUnmount: 在组件即将被卸载时调用。
4. 错误处理:
componentDidCatch: 在子组件抛出错误后调用,用于捕获组件渲染期间发生的错误。
React类组件:
在react类组件中,可以显式的使用生命周期。
举例:
import React, { Component } from "react";
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
componentDidMount() {
// 在组件挂载后,启动一个定时器,每秒更新一次 count 状态
this.interval = setInterval(() => {
this.setState({ count: this.state.count + 1 });
}, 1000);
}
componentWillUnmount() {
// 在组件卸载前清理定时器
clearInterval(this.interval);
}
render() {
return (
<div>
<h1>My Simple Component</h1>
<p>Count: {this.state.count}</p>
</div>
);
}
}
export default MyComponent;
React函数式组件:
React Hooks
React 开发中的主流更推荐函数式组件配合 React Hooks。除非对于某些复杂的场景,需要明确的更多的功能和生命周期方法。
而react的函数式组件之前没有生命周期方法。但是,从 React 16.8 版本开始,引入了 React Hooks,使得函数式组件也能够拥有类似生命周期的功能。通过useState , useEffect , useContext , useCallback ,useRef , useMemo等Hooks模拟生命周期行为,其调用和效果更为隐式。
这里重点举例useEffect :
他是一个副作用钩子,替代componentDidMount 和 componentDidUpdate, shouldComponentUpdate,componentWillUnmount等生命周期,通过灵活运用useEffect,你可以模拟React类组件中大多数生命周期方法的行为。
它接受2个参数,第一个参数(必传)为一个执行callback函数,第二个参数(可选)是一个依赖数组。而参数不同,返回值不同时useEffect的使用场景也不同。
1. 当callback函数return一个清理函数,在组件卸载或下次渲染前(如果有依赖数组且依赖改变时),React会先调用这个返回的清理函数,避免造成内存泄漏或其他副作用
useEffect(async () => {
if (text === 'hello World') {
// 执行拉取数据
}else{
text=await getData();
}
// 可以return一个清理函数
return () => {
// 清理副作用: 比如取消订阅事件,清除定时器等
}
}, [text]);
2. 当没有return清理函数,且没有第二个参数(或者第二个参数为空数组)时,useEffect只会在第一次DOM挂载时执行一次,之后组件再重新渲染也不会执行。相当于执行一次的componentDidMount。
useEffect(() => {
...
// 如果没有第二个参数或是空数组,表示只在组件挂载和卸载的时候执行一次
},[]);
3. 当callback函数返回一个清理函数,并且没有第二个参数(或者第二个参数为空数组)时,相当于执行一次的componentDidMount和componentWillUnmount。
useEffect(async () => {
if (text === 'hello World') {
// 执行拉取数据
}else{
text=await getData();
}
// 可以return一个清理函数
return () => {
// 清理副作用: 比如取消订阅事件,清除定时器等
}
}, []);
4. 当第二个参数依赖数组不为空时,useEffect首次渲染后执行,之后每当依赖数组中的某个值发生变化时再次执行。相当于执行componentDidMount、componentDidUpdate和componentWillUnmount的组合行为。
useEffect(() => {
console.log('componentDidUpdate 相关操作,仅当依赖项变化时执行');
}, [ValueA,ValueB]); // 依赖数组中的值变化时触发
结语:
感谢您花时间阅读这篇分享文章。希望通过这篇文章,您能对vue和react的生命周期钩子和hooks有了更深入的了解和认识。
转载自:https://juejin.cn/post/7376864081788485672