当前位置: 首页 > news >正文

前端面经-VUE3篇(二)--vue3组件知识(二)依赖注入、异步组件、生命周期、组合式函数、插件

目录

一、依赖注入

1、 依赖注入是什么?

 2、最基础的使用

 3、为什么使用依赖注入?

4、 使用 Symbol 作注入名

 二、异步组件

1、什么是异步组件?

2、最基础用法:defineAsyncComponent

 3、在模板中使用异步组件

4、配置加载状态:加载提示 / 超时 / 错误处理

三、生命周期 

 1、生命周期的本质:组件从“出生”到“死亡”的过程

2、生命周期钩子总览

3、 各生命周期钩子的详细解释

1. setup()

2. onBeforeMount()

3. onMounted()

4. onBeforeUpdate()

5.onUpdated()

6. onBeforeUnmount()

7. onUnmounted()

4、钩子参数​

 四、组合式函数

1、什么是组合式函数?

2、组合式函数的结构

3、组合式函数的核心特征

 4、组合式函数能做什么?

5、实战场景汇总

6、总结一句话

 五、插件

1、什么是 Vue 插件?

2、插件的核心格式

 3、注册方式

4、插件内部能做的事(功能总结)

5、注意事项

6、总结一句话


一、依赖注入

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

1、 依赖注入是什么?

依赖注入是一种让“祖先组件提供”和“后代组件注入使用”的机制,使用 provideinject 配合实现。

  • provide(key, value)祖先组件中声明可供后代使用的内容

  • inject(key)后代组件中声明需要注入的内容

 2、最基础的使用

父组件(祖先)使用 provide
<script setup>
import { provide } from 'vue'
provide('color', 'blue')
</script>子组件(任意后代)使用 inject
<script setup>
import { inject } from 'vue'const color = inject('color')
</script>
<template><p style="color: {{ color }}">我是注入的颜色</p>
</template>
✅ 这样,子组件就无需 props,可以跨越多层组件拿到祖先组件提供的数据。

如果提供的值是一个 ref,注入进来的会是该 ref 对象,而不会自动解包为其内部的值。这使得注入方组件能够通过 ref 对象保持了和供给方的响应性链接。 

 3、为什么使用依赖注入?

传统方式问题
使用 props需要每层组件手动传递,维护困难
使用 Vuex / pinia重,但适合全局状态
使用 event bus不推荐,易维护混乱

✅ 依赖注入适合:

  • 状态共享(如配置、主题、权限)

  • 插件式封装(如表单、组件注册)

  • 面向组合逻辑的解耦

默认值与类型检查

如果子组件注入的 key 不存在,返回值为 undefined,你可以设置默认值:

const theme = inject('theme', 'light') // 默认值 fallback

你还可以传入工厂函数作为默认值:

const config = inject('config', () => ({ color: 'blue' }))

4、 使用 Symbol 作注入名

但如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,建议最好使用 Symbol 来作为注入名以避免潜在的冲突。 

// keys.js
export const myInjectionKey = Symbol()// 在供给方组件中
import { provide } from 'vue'
import { myInjectionKey } from './keys.js'
provide(myInjectionKey, { /* 要提供的数据 */
})// 注入方组件
import { inject } from 'vue'
import { myInjectionKey } from './keys.js'const injected = inject(myInjectionKey)

 二、异步组件

Vue 的 异步组件(Async Components) 是一种优化性能与用户体验的机制,它允许你在需要时按需加载某个组件,而不是在应用启动时一次性加载全部组件。

异步组件在构建大型应用、提升首屏加载速度、实现懒加载等场景中非常重要,Vue 为此提供了专门的语法和加载配置。

1、什么是异步组件?

异步组件是指:组件不是立即加载的,而是在需要时才异步地被加载

它的核心思想是:“用的时候才加载”,这对以下场景非常有用:

  • 页面拆分(如路由页面)

  • 大型组件库懒加载

  • 多个组件中只有部分在运行中用到

2、最基础用法:defineAsyncComponent

Vue 提供了官方函数 defineAsyncComponent() 来创建异步组件。

 基本语法:

import { defineAsyncComponent } from 'vue'const AsyncComponent = defineAsyncComponent(() =>import('./MyHeavyComponent.vue')
)

这个组件会被延迟加载,只有在模板中首次渲染它时,Vue 才会触发 import() 加载它对应的文件。

 3、在模板中使用异步组件

<template><div><AsyncComponent /></div>
</template><script setup>
import { defineAsyncComponent } from 'vue'const AsyncComponent = defineAsyncComponent(() =>import('./MyHeavyComponent.vue')
)
</script>

4、配置加载状态:加载提示 / 超时 / 错误处理

defineAsyncComponent 还可以接受一个对象,配置异步加载的过程行为。

 

import { defineAsyncComponent } from 'vue'const AsyncComponent = defineAsyncComponent({loader: () => import('./MyHeavyComponent.vue'),// 加载时展示的组件loadingComponent: LoadingSpinner,// 出错时展示的组件errorComponent: ErrorMessage,// 延迟多长时间显示 loadingComponent(毫秒)delay: 200,// 加载超时时间(毫秒)timeout: 3000,// 出错时重试机制onError(error, retry, fail, attempts) {if (attempts <= 3) {retry()} else {fail()}}
})

各配置解释:

选项功能
loader必填。返回组件的异步加载 Promise(即 import()
loadingComponent加载过程中显示的 UI
errorComponent加载失败后显示的 UI
delay加载多少毫秒后才显示 loading
timeout超过此时间未加载完成视为失败
onError异步加载失败时自定义处理(可自动重试)

注意:Vue Router 内部会自动处理 loading 状态,不需要你手动 defineAsyncComponent

三、生命周期 

Vue 的生命周期(Lifecycle)指的是 Vue 组件从创建到销毁过程中经历的一系列阶段性钩子函数,你可以在这些钩子中执行逻辑,如数据初始化、DOM 操作、网络请求、清理等。

每个 Vue 组件实例在其创建过程中都会经历一系列初始化步骤,例如设置数据监听、编译模板、挂载 DOM,直到被销毁。Vue 提供了生命周期钩子函数,让我们有机会在不同阶段插入代码。

 1、生命周期的本质:组件从“出生”到“死亡”的过程

 整个过程大致如下:

创建阶段 → 挂载阶段 → 更新阶段 → 销毁阶段 

2、生命周期钩子总览

阶段钩子函数作用
创建前setup()Vue 3 中唯一入口
挂载前onBeforeMount()组件尚未挂载,DOM 还未生成
挂载后onMounted()组件已挂载,DOM 可操作
更新前onBeforeUpdate()响应式数据变更,但 DOM 还未更新
更新后onUpdated()DOM 更新完毕,可做响应处理
卸载前onBeforeUnmount()组件将被销毁,做清理前工作
卸载后onUnmounted()已销毁,清理资源、解绑事件等

3、 各生命周期钩子的详细解释

1. setup()

阶段:组件创建阶段(最先执行)
调用时机:组件实例刚创建,datapropsmethods 都还没绑定到 this
作用

  • 是组合式 API 的入口;

  • 用来声明响应式数据、props、emit、watch、计算属性等;

  • 不能访问 this

  • 返回的变量会暴露给模板使用。

2. onBeforeMount()

阶段:挂载前
调用时机:组件即将挂载到 DOM(el 创建完毕但未插入 DOM)
作用

  • 此时模板已编译,但 DOM 未挂载;

  • 可以进行某些准备工作或日志记录。

常见用途

  • 初始化数据日志;

  • 注册未依赖 DOM 的第三方逻辑。

从组件“出生到上场”来理解生命周期

你可以把组件想象成一个“舞台演员”:

阶段比喻生命周期钩子
写好剧本编译模板等准备工作setup()
穿好衣服化妆DOM 虚拟结构准备就绪onBeforeMount()
走上舞台挂载 DOM,出现在页面onMounted()

所以 onBeforeMount() 就是演员 刚准备好,马上就要上场 的那一刻。

 Vue 在内部的执行流程:

setup() → 编译模板 → 创建虚拟 DOM → 
→ 🔹onBeforeMount() →
→ 渲染并插入真实 DOM →
→ 🔹onMounted()

 onBeforeMount 做了什么?

  • 组件已经准备好数据(比如 propsref);

  • 已经生成了虚拟 DOM(VNode);

  • 但还没有插入真实页面中

  • 所以此时你不能直接操作 DOM 元素

能干什么?

虽然还不能访问 DOM,但可以: 

  • 准备数据(如果依赖 DOM 可延迟);

  • 进行日志埋点或调试;

  • 记录组件加载时间;

  • 检查组件状态是否完整;

  • 准备动画过渡参数(比如进入动画前的状态)。

3. onMounted()

阶段:挂载后
调用时机首次 DOM 渲染完成,所有 DOM 元素可操作
作用

  • 执行需要访问 DOM 的逻辑;

  • 发起初始请求;

  • 注册事件监听器;

  • 引入第三方库(如 ECharts、Swiper)。

常见用途

  • 页面初始化请求;

  • DOM 操作(如获取滚动容器、焦点);

  • 动画执行。

你可以把它理解为:

“我的组件已经出现在页面上了,现在可以操作它的 DOM、做异步请求、初始化动画、注册事件等。”

可以用 onMounted() 做哪些事?

用途说明
✅ 操作 DOM可以安全地访问 document.querySelectorref 引用的元素
✅ 发起 API 请求初始化组件数据,如加载表格数据、详情数据等
✅ 注册监听器注册 scrollresizekeyboard 等全局事件
✅ 使用第三方库比如挂载图表(ECharts)、富文本编辑器(Quill)等
✅ 初始化动画初始化进入动画或过渡效果
✅ 上报埋点发送统计日志、埋点监控等

4. onBeforeUpdate()

阶段:更新前
调用时机:响应式状态变化,DOM 还未更新
作用

  • 可用于比较新旧状态;

  • 做一些缓存或临时逻辑。

注意事项

  • 不建议操作 DOM;

  • 不要进行异步逻辑处理。

onBeforeUpdate() 是 Vue 组件中的一个更新阶段生命周期钩子,它在 响应式数据发生变化、DOM 还没有更新之前 被调用。

你可以把它理解为:

“组件数据变了,DOM 马上要重新渲染了,现在是我插手干预的最后机会。”

onBeforeUpdate() 的作用

用途说明
✅ 获取旧的 DOM 状态DOM 还没变,你可以访问“变化前”的样子
✅ 计算更新前的一些值比如滚动高度、旧位置
✅ 清除旧状态标记如之前的样式、数据缓存
❌ 不适合做异步请求更新前阶段不能引起新响应式更新(否则会递归)

5.onUpdated()

阶段:更新后
调用时机:响应式数据更新完成,DOM 也已更新
作用

  • 可以对新 DOM 做处理;

  • 常用于监听局部 DOM 变化后执行逻辑。

onUpdated() 是 Vue 组件在 响应式数据变更导致 DOM 更新完成后 自动调用的生命周期钩子。

你可以理解为:

“Vue 已经把新数据同步到了页面上,现在你可以看到更新后的 DOM,想操作它、获取它的新状态、触发动画等等——就靠 onUpdated()。”

onUpdated() 能做什么?

能做的事应用场景
✅ 读取更新后的 DOM 状态比如新的高度、内容、布局
✅ 执行过渡动画、样式变化比如 fade-in、滚动动画等
✅ 动态调整布局比如等高布局、表格自适应列宽
✅ 与旧值对比onBeforeUpdate() 配合使用
❌ 不推荐用来发请求页面每次更新都会触发,可能频繁调用

 和onBeforeUpdate区别

项目onBeforeUpdate()onUpdated()
调用时机DOM 更新前DOM 更新后
访问的是旧 DOM新 DOM
场景缓存、准备、清理更新后调整布局、动画
能否操作新结构❌ 不行✅ 可以

理解类比:装修房子

你可以把 Vue 更新比喻成“家装翻新”:

  • onBeforeUpdate():工人刚拿到设计图纸,准备改造,但还没开始动工;

  • onUpdated():已经把墙刷好、灯装上、地板换了,可以检查结果了。

6. onBeforeUnmount()

阶段:卸载前
调用时机:组件即将从页面上被卸载
作用

  • 做清理工作,如清除定时器、取消监听器;

  • 防止内存泄漏;

  • 通知外部容器取消操作。

 onBeforeUnmount() 是 Vue 组件即将被销毁前调用的生命周期钩子。

你可以理解为:

“Vue 准备把这个组件从页面中移除,我现在有一个机会做一些清理工作或资源释放。”

适合用 onBeforeUnmount() 做哪些事?

用途举例
✅ 清除定时器clearInterval()clearTimeout()
✅ 取消网络请求调用 AbortController.abort() 或取消 token
✅ 移除事件监听器removeEventListener()
✅ 停止动画或任务比如取消动画帧 cancelAnimationFrame()
✅ 通知父组件或全局状态通知组件退出、清除缓存等

7. onUnmounted()

阶段:卸载后
调用时机:组件 DOM 被完全移除
作用

  • 彻底释放资源;

  • 日志记录、事件通知等。

注意事项

  • 通常清理逻辑建议放在 onBeforeUnmount()onUnmounted() 比较少用。

 onUnmounted() 是 Vue 组件在 被销毁之后 自动调用的生命周期钩子。

你可以理解为:

“Vue 已经把这个组件从页面中移除了,DOM 不再存在,响应式状态也都释放了。这是我最后一次处理事情的机会。”

onUnmounted() 的典型用途

用途示例
✅ 日志记录 / 调试组件销毁后打 log
✅ 通知外部状态如 Vuex、Pinia 中的状态重置
✅ 执行异步销毁操作提交状态到后端、更新埋点日志等
✅ 销毁订阅 / 解耦逻辑清理比如 event bus 或 WebSocket 等注册事件

onBeforeUnmount() 的区别

钩子时机是否可以访问 DOM?用途
onBeforeUnmount()销毁前✅ 是清除定时器/监听器
onUnmounted()销毁后❌ 否日志、通知、埋点、最后状态更新

一个指令的定义对象可以提供几种钩子函数 (都是可选的): 

const myDirective = {// 在绑定元素的 attribute 前// 或事件监听器应用前调用created(el, binding, vnode) {// 下面会介绍各个参数的细节},// 在元素被插入到 DOM 前调用beforeMount(el, binding, vnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都挂载完成后调用mounted(el, binding, vnode) {},// 绑定元素的父组件更新前调用beforeUpdate(el, binding, vnode, prevVnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都更新后调用updated(el, binding, vnode, prevVnode) {},// 绑定元素的父组件卸载前调用beforeUnmount(el, binding, vnode) {},// 绑定元素的父组件卸载后调用unmounted(el, binding, vnode) {}
}

4、钩子参数​

指令的钩子会传递以下几种参数:

  • el:指令绑定到的元素。这可以用于直接操作 DOM。

  • binding:一个对象,包含以下属性。

    • value:传递给指令的值。例如在 v-my-directive="1 + 1" 中,值是 2
    • oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
    • arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 "foo"
    • modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }
    • instance:使用该指令的组件实例。
    • dir:指令的定义对象。
  • vnode:代表绑定元素的底层 VNode。

  • prevVnode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

 四、组合式函数

 Vue 3 中的组合式函数(Composables)是基于组合式 API 构建的一个逻辑复用机制,它允许你将组件的状态逻辑抽离成可重用的函数,这种方式比 Vue 2 的 Mixin、HOC 更清晰、更灵活、更易维护。

1、什么是组合式函数?

组合式函数是一个以 useXxx() 命名的普通 JavaScript 函数,在其中使用 Vue 的组合式 API(如 ref, reactive, watch, computed 等),然后将这些逻辑封装并返回供多个组件使用。

简化理解就是:

“把多个组件中重复的响应式逻辑、状态、侦听器等代码封装成函数,复用它们。”

2、组合式函数的结构

一个组合式函数的基本结构如下:

// useCounter.js
import { ref } from 'vue'export function useCounter() {const count = ref(0)function increment() {count.value++}return {count,increment}
}
在组件中使用它:
<script setup>
import { useCounter } from './useCounter'const { count, increment } = useCounter()
</script><template><button @click="increment">点击:{{ count }}</button>
</template>

3、组合式函数的核心特征

特征描述
✅ 可重用不同组件可调用相同的逻辑函数
✅ 组合式 API 支持内部可以使用任何 ref、reactive、watch、computed 等
✅ 与组件解耦逻辑不再依赖组件上下文
✅ 类型推导友好TypeScript 支持极好
✅ 易测试普通函数,易于单元测试

 4、组合式函数能做什么?

1. 封装状态逻辑export function useToggle(initial = false) {const state = ref(initial)const toggle = () => (state.value = !state.value)return { state, toggle }
}
2. 封装异步请求逻辑export function useFetch(url) {const data = ref(null)const error = ref(null)fetch(url).then(res => res.json()).then(json => (data.value = json)).catch(err => (error.value = err))return { data, error }
}
3. 封装监听器逻辑export function useMouse() {const x = ref(0)const y = ref(0)function update(e) {x.value = e.pageXy.value = e.pageY}onMounted(() => window.addEventListener('mousemove', update))onBeforeUnmount(() => window.removeEventListener('mousemove', update))return { x, y }
}

5、实战场景汇总

场景封装为组合式函数
表单验证useFormValidation()
网络请求useFetch(), useAxios()
用户状态管理useUser()
页面权限控制usePermission()
响应式缓存useLocalStorage(), useSessionStorage()
主题/系统设置useTheme(), useSystemConfig()
响应式计数器useCounter()

6、总结一句话

组合式函数是 Vue 3 中最推荐的逻辑复用机制,它允许你把多个组件重复的状态、侦听器、生命周期逻辑提取为独立函数,提高代码复用性、可维护性和清晰度

 五、插件

1、什么是 Vue 插件?

Vue 插件(Plugin)是一个可以通过 app.use() 方法注册到 Vue 应用中的扩展模块。

它通常用于:

  • 向应用注入功能(如添加全局方法、指令、组件等)

  • 对整个应用进行配置或初始化

  • 集成第三方库(如 Vue Router、Vuex、Pinia、Element Plus 等)

2、插件的核心格式

Vue 插件其实就是一个具有 install(app, options) 方法的对象或函数:

 插件的标准写法(对象形式):

// MyPlugin.js
export default {install(app, options) {// 1. 添加全局方法app.config.globalProperties.$hello = () => {console.log('Hello from plugin!')}// 2. 注册全局组件app.component('MyGlobalComp', {template: `<div>I am global</div>`})// 3. 添加全局指令app.directive('focus', {mounted(el) {el.focus()}})// 4. 注入 provide/inject 数据app.provide('pluginName', 'MyPlugin')}
}

 3、注册方式

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import MyPlugin from './MyPlugin'const app = createApp(App)
app.use(MyPlugin, { customOption: true }) // 安装插件
app.mount('#app')

4、插件内部能做的事(功能总结)

功能用法
注册全局组件app.component('Xxx', Component)
注册全局指令app.directive('xxx', definition)
添加全局属性app.config.globalProperties.$xxx = fn
使用 provide/inject 传递全局依赖app.provide('xxx', value)
启动外部库或执行初始化如初始化配置项、加载配置文件等

5、注意事项

注意点说明
插件必须使用 app.use() 安装否则不会执行其 install() 方法
不要滥用全局属性app.config.globalProperties 会污染组件上下文
插件之间避免命名冲突推荐用命名空间前缀(如 $myXxx
插件应保持纯函数和无副作用避免影响应用的稳定性

6、总结一句话

Vue 插件是通过 app.use() 安装的功能扩展模块,适合封装和共享全局逻辑,如注册组件、添加方法、集成第三方库等,是构建大型项目或封装组件库的重要机制。

 

相关文章:

  • 3.0/Q1,Charls最新文章解读
  • yolov5 train笔记4 roboflow
  • Linux《进程概念(下)》
  • 射频指标互调与交调简略
  • RPG7.准备GAS的工作
  • Linux 的 epoll 与 Windows 的 IOCP 详解
  • 重塑数学边界:人工智能如何引领数学研究的新纪元
  • Transformer架构:基于自注意力机制推动NLP革命性突破
  • 有机玻璃材质数据采集活性炭吸附气体中二氧化硫实验装置
  • 别样健康养生之道
  • 【Arthas】火焰图优化应用CPU(问题原因:获取调用栈)
  • sonar-scanner在扫描JAVA项目时为什么需要感知.class文件
  • FPGA DDR4多通道管理控制器设计
  • 影楼精修-露齿笑算法解析
  • Python Cookbook-6.18 用__init__参数自动初始化实例变量
  • Pillow 玩图术:轻松获取图片尺寸和颜色模式
  • python进阶(1)字符串
  • Vue中的过滤器知道多少?从是什么、怎么用、应用场景、原理分析、示例解释
  • luaopen系列标准库使用解析
  • 生成式 AI 与 AI 的区别
  • “五一”假期客流增加,多地提升铁路运力并强化服务
  • “五一”假期首日迎出游高峰:火车站人流“堪比春运”,热门景区门票预订量同比增三成
  • 视频丨英伟达总裁黄仁勋:美勿幻想AI领域速胜中国
  • 澎湃读报丨解放日报8个版聚焦:牢记嘱托,砥砺奋进
  • 5月起,这些新规将施行
  • 为治理商家“卷款跑路”“退卡难”,预付式消费司法解释5月起实施