组件各种情况的重新渲染和钩子函数触发时机
onMounted, onUpdated, router-view, keep-alive
vue
<!--
@file: Home.vue
@author: pan
-->
<script lang="ts">
export default {
name: 'Home',
}
</script>
<script setup lang="ts">
import { onMounted, onUpdated, ref } from 'vue'
let mountedDate = ref<string>()
let updatedDate = ref<string>()
onMounted(() => {
console.log('onMounted Home')
/**
* 修改 mountedDate 会触发一次 界面重新渲染,然后触发 onUpdated 钩子。因为 template 代码块中使用了该 响应式变量
*/
mountedDate.value = new Date().toLocaleTimeString()
})
onUpdated(() => {
/*
* 因为 onMounted 之后执行了 mountedDate.value = new Date().toLocaleTimeString() ,
* 更新了一个render函数(template代码块可以看作是render函数)中使用到的响应式变量所以会触发界面重新渲染,
* 因此会在 onMounted 之后,立刻触发 onUpdated
*/
/**
* 使用了 keep-alive 之后,只要路由切换回当前组件,就会触发 onUpdated 钩子。
* 这里就引发一个思考:什么时候会触发 onUpdated 钩子?
* 答:vue引发的界面重新渲染一定触发 onUpdated 钩子
* 暂时发现,以下两种形式的界面重新渲染会触发 onUpdated 钩子:
* 1. render 函数(即:template 代码块)中使用到的响应式变量发生了变更,会触发界面重新渲染
* 2. 使用了 router-view 然后被 keep-alive 缓存的组件,路由切换时,组件从冻结状态变为激活状态,会触发界面重新渲染(即使当前界面和上一次界面一摸一样,那算界面重新渲染。暂时没有办法解释这种行为,因为如果只是使用 keep-alive 缓存组件,而不使用 router-view,此时组件从冻结状态变成激活状态是不会触发 onUpdated 钩子的)
*/
console.log('onUpdated Home')
/**
* onUpdated 中又修改了一个 render 函数中的响应式变量,所以会引起界面更新,所以会在界面更新之后又触发一次 onUpdated,
* 之所以不会一直这样触发下去,是因为两次界面重绘间隔事件很短,使得 updatedDate 第一次的值和第二次的值是一样的,所以才没有形成 onUpdated 无限循环。
* 只要延迟更新 updatedDate 就会形成 onUpdated 无限循环
*/
updatedDate.value = new Date().toLocaleTimeString()
})
</script>
<template>
<div>mountedDate: {{ mountedDate }}</div>
<!-- <div>updatedDate: {{ updatedDate }}</div> -->
<!-- <div>renderDate: {{ new Date().toLocaleTimeString() }}</div> -->
<ul>
<li><router-link to="/test-01">Go test 01</router-link></li>
<li><router-link to="/test-02">Go test 02</router-link></li>
</ul>
<hr />
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component"></component>
</keep-alive>
</router-view>
</template>
<style lang="scss" scoped></style>