前端笔记-Vue3(下)

学习参考视频:尚硅谷Vue3入门到实战,最新版vue3+TypeScript前端开发教程_哔哩哔哩_bilibili

vue3学习目标:

VUE 31、Vue3架构与设计理念
2、组合式API(Composition API)
3、常用API:ref、reactive、watch、computed
4、Vue3的生命周期
5、组件间通信(props、emit、defineModel)
6、了解插槽

Vue 生命周期钩子详解(Vue 2 & Vue 3 对比)

生命周期概念图解

https://cn.vuejs.org/assets/lifecycle_zh-CN.W0MNXI0C.png

生命周期阶段对比表

阶段Vue 2 钩子Vue 3 钩子触发时机典型用途
创建beforeCreatesetup()组件实例刚被创建初始化响应式数据
createdsetup()数据观测/事件配置完成异步请求数据
挂载beforeMountonBeforeMount模板编译/挂载前访问/操作DOM前的最后机会
mountedonMounted组件挂载到DOM后操作DOM、初始化第三方库
更新beforeUpdateonBeforeUpdate数据变化,DOM更新前获取更新前的DOM状态
updatedonUpdated虚拟DOM重新渲染后执行依赖DOM的操作
销毁beforeDestroyonBeforeUnmount实例销毁前清除定时器/取消订阅
destroyedonUnmounted实例销毁后清理内存/移除事件监听

Vue 3 生命周期示例

<template><div class="demo"><h2>计数器: {{ count }}</h2><button @click="increment">增加</button><button @click="showComponent = false">卸载组件</button><ChildComponent v-if="showComponent" /></div>
</template><script setup lang="ts">
import { ref, onMounted, onUpdated, onUnmounted } from 'vue'
import ChildComponent from './ChildComponent.vue'// 1. 创建阶段(setup)
const count = ref(0)
const showComponent = ref(true)console.log('1. setup阶段 - 数据初始化完成')// 3. 挂载阶段
onMounted(() => {console.log('3. mounted - 组件已挂载到DOM')// 这里可以安全地操作DOMdocument.title = `当前计数: ${count.value}`
})// 4. 更新阶段
onUpdated(() => {console.log('4. updated - DOM已更新')// 避免在这里修改状态,可能导致无限循环!
})// 方法
function increment() {count.value++console.log('2. 数据变化触发更新流程')
}// 子组件示例
const ChildComponent = {setup() {onMounted(() => {console.log('子组件 mounted')})onUnmounted(() => {console.log('子组件 unmounted')})return {}},template: '<div>子组件内容</div>'
}
</script>

生命周期执行顺序演示

  1. 组件初始化时:

    1. setup阶段 - 数据初始化完成
    3. mounted - 组件已挂载到DOM
  2. 点击"增加"按钮时:

    2. 数据变化触发更新流程
    4. updated - DOM已更新
  3. 点击"卸载组件"时:

    子组件 unmounted

 挂载阶段完整顺序(父 → 子)

  1. 父组件​ setup() 执行
  2. 父组件​ onBeforeMount
  3. 子组件​ setup() 执行
  4. 子组件​ onBeforeMount
  5. 子组件​ onMounted(子组件先完成挂载)
  6. 父组件​ onMounted(父组件最后完成挂载)

常用钩子使用场景

1. onMounted - 最常用

onMounted(async () => {// 加载初始数据const response = await fetch('/api/data')data.value = await response.json()// 初始化图表chart = new Chart(document.getElementById('chart'), {// 配置项})
})

2. onUpdated - 谨慎使用

onUpdated(() => {// 典型用例:自动滚动到底部listContainer.value.scrollTop = listContainer.value.scrollHeight
})

3. onUnmounted - 资源清理

onUnmounted(() => {// 清除定时器clearInterval(timer)// 取消事件监听window.removeEventListener('resize', handleResize)// 销毁第三方库实例chart?.destroy()
})

Vue 2 与 Vue 3 生命周期对比

关键区别:

  1. ​Vue 3 使用 setup 替代了 beforeCreatecreated
  2. 所有钩子都需要显式导入
  3. 命名更语义化(unmount 替代 destroy)​
  4. 组合式API让相关代码更集中

补充 自定义Hooks

什么是自定义 Hook?

自定义 Hook 是 Vue 3 组合式 API 的核心实践方式,本质是一个封装了响应式逻辑的函数。它解决了两个核心问题:

  1. 逻辑复用​ - 避免重复代码
  2. 关注点分离​ - 让组件更专注于模板渲染

就比如,在写到一个组件里面存着在不同逻辑的数据和处理数据的方法时,全部都混用了

<template><div class="hooks-test"><h2>当前求和为:{{sum}}</h2><button @click="add">点我+1</button><hr><img v-for="(dog,index) in dogList" :src="dog" :key="index"><br><button @click="getDog">再来一只狗</button></div>
</template><script lang="ts" setup>import { ref,reactive } from 'vue'import axios from 'axios'    let sum = ref(0)let dogList = reactive(['https:\/\/images.dog.ceo\/breeds\/pembroke\/n02113023_2390.jpg'])function add(){sum.value += 1}// function getDog(){//   axios.get('https://dog.ceo/api/breeds/image/random')//  .then(res => {//     dogList.push(res.data.message)//   })// }async function getDog(){try {let result = await axios.get('https://dog.ceo/api/breeds/image/random')dogList.push(result.data.message)} catch (error) {alert(error)}}</script><style scoped>
.hooks-test{background-color: beige;padding: 20px;text-align: center;border: 1px solid black;
}
img{height: 200px;margin: 20px;
}
</style>

 图示代码又处理数字数据又处理狗狗数据,数据和处理逻辑没有分开,导致代码阅读时有一定的障碍,这个时候我们就可以使用hooks自定义,将实现同一个功能所需要的数据和方法单独封装在一起

Hook 基础结构

首先注意,hook命名规范是useXxxx.js/ts

1. 计数器 Hook 示例 (useCounter.ts)

import { ref, onMounted } from 'vue'export default function(initialValue = 0) {// 响应式数据const count = ref(initialValue)// 操作方法const increment = () => count.value++const decrement = () => count.value--const reset = () => count.value = initialValue// 生命周期onMounted(() => {console.log('计数器Hook已挂载')})// 暴露给组件的APIreturn {count,increment,decrement,reset}
}

2. 异步数据 Hook 示例 (useFetch.ts)

import { reactive, onMounted } from 'vue'
import axios from 'axios'export default function(url: string) {const state = reactive({data: null as any,loading: false,error: null as Error | null})const fetchData = async () => {state.loading = truetry {const response = await axios.get(url)state.data = response.data} catch (err) {state.error = err as Error} finally {state.loading = false}}onMounted(fetchData)return {...state,refetch: fetchData}
}

组件中使用 Hook

1. 基础用法

<template><div><p>Count: {{ counter.count }}</p><button @click="counter.increment">+</button><button @click="counter.decrement">-</button><button @click="counter.reset">Reset</button></div>
</template><script setup lang="ts">
import useCounter from '@/hooks/useCounter'const counter = useCounter(10) // 初始值10
</script>

2. 组合多个 Hook

<template><div><!-- 计数器 --><div>{{ counter.count }}</div><!-- 异步数据 --><div v-if="posts.loading">Loading...</div><div v-else>{{ posts.data }}</div></div>
</template><script setup lang="ts">
import useCounter from '@/hooks/useCounter'
import useFetch from '@/hooks/useFetch'const counter = useCounter()
const posts = useFetch('/api/posts')
</script>

最佳实践

1. 命名规范

  • 始终以 use 开头 (useXxx)
  • 一个文件只包含一个 Hook
  • 放在 src/hooks 目录下

2. 类型安全

// useUser.ts
import { ref } from 'vue'interface User {id: numbername: stringemail: string
}export default function() {const user = ref<User | null>(null)return {user}
}

3. 复杂 Hook 示例 (usePagination.ts)

import { reactive, computed } from 'vue'export default function(totalItems: number, perPage = 10) {const state = reactive({currentPage: 1,perPage})const totalPages = computed(() => Math.ceil(totalItems / state.perPage))const nextPage = () => {if (state.currentPage < totalPages.value) {state.currentPage++}}return {...state,totalPages,nextPage}
}

与 Vue 2 Mixins 对比

特性自定义 HookMixins
代码组织按功能组织按选项合并
命名冲突无(可重命名解构)容易冲突
类型支持完整 TypeScript 支持支持有限
逻辑复用显式导入全局混入
调试清晰的调用栈难以追踪逻辑来源

高级技巧

1. 本地存储 Hook (useLocalStorage.ts)

import { ref, watch } from 'vue'export default function(key: string, defaultValue: any) {const data = ref(JSON.parse(localStorage.getItem(key) || 'null') || defaultValue)watch(data, (newVal) => {localStorage.setItem(key, JSON.stringify(newVal))}, { deep: true })return data
}

2. 鼠标位置 Hook (useMouse.ts)

import { ref, onMounted, onUnmounted } from 'vue'export default function() {const x = ref(0)const y = ref(0)const update = (e: MouseEvent) => {x.value = e.pageXy.value = e.pageY}onMounted(() => window.addEventListener('mousemove', update))onUnmounted(() => window.removeEventListener('mousemove', update))return { x, y }
}

常见问题解决

1. Hook 之间共享状态

// useSharedState.ts
import { reactive } from 'vue'const state = reactive({count: 0
})export function useSharedCounter() {const increment = () => state.count++return {count: state.count,increment}
}

2. 响应式解构问题

// ❌ 错误 - 失去响应性
const { count, increment } = useCounter()// ✅ 正确 - 保持响应性
const counter = useCounter()
// 在模板中使用 counter.count

(未完) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git远程操作与标签管理

目录 1.理解分布式版本控制系统 2.远程仓库 3.新建远程仓库 4.克隆远程仓库 5.向远程仓库推送 6.拉取远程仓库 7.配置Git 7.1.忽略特殊文件 7.2.给命令配置别名 8.标签管理 8.1.理解标签 8.2.创建标签 8.3.操作标签 1.理解分布式版本控制系统 Git是目前世界上…

Vue3:component(组件:uniapp版本)

目录 一、基本概述二、基本使用(父传子)三、插槽四、子传父 一、基本概述 在项目的开发过程中&#xff0c;页面上井场会出现一些通用的内容&#xff0c;例如头部的导航栏&#xff0c;如果我们每一个页面都去写一遍&#xff0c;那实在是太繁琐了&#xff0c;所以&#xff0c;我…

C#语言实现PDF转Excel

实现效果 第三方库 ClosedXML iTextSharp 实现源码 using System.Text; using iTextSharp.text.pdf; using iTextSharp.text.pdf.parser; using System.Text.RegularExpressions; using ClosedXML.Excel;namespace PdfToExcel_winform {public partial class MainForm : For…

如何将IDP映射属性添加,到accountToken中 方便项目获取登录人信息

✅ 目标 你想要&#xff1a; 用户通过 IdP 登录&#xff08;SAML 或 OAuth2&#xff09;Keycloak 自动将 IdP 返回的属性&#xff08;如&#xff1a;email、name、role 等&#xff09;映射到用户账户中并把这些属性加入到用户登录返回的 Access Token 中&#xff0c;供业务系…

JSON-RPC远程控制

文章目录 &#x1f310; 一、什么是 JSON-RPC&#xff1f;&#x1f4ec; 二、通信过程1️⃣ 客户端发起请求2️⃣ 服务端处理请求&#xff0c;调用方法&#xff0c;返回结果 &#x1f4d1; 三、重要字段说明&#x1f6e0;️ 四、核心函数与概念&#xff08;结合你的代码&#x…

芝法酱躺平攻略(21)——kafka安装和使用

本节内容比较初级&#xff0c;故接着躺平攻略写 一、官网的下载 1.1 下载解压 首先&#xff0c;去官网下载jar包&#xff0c;放进linux中&#xff0c;解压到对应位置。 我的位置放在/WORK/MIDDLEWARE/kafka/4.0 1.2 常见配置 # 每个topic默认的分片数 num.properties4 # 数…

AutoSAR从概念到实践系列之MCAL篇(二)——Mcu模块配置及代码详解(上)

欢迎大家学习我的《AutoSAR从概念到实践系列之MCAL篇》系列课程,我是分享人M哥,目前从事车载控制器的软件开发及测试工作。 学习过程中如有任何疑问,可底下评论! 如果觉得文章内容在工作学习中有帮助到你,麻烦点赞收藏评论+关注走一波!感谢各位的支持! 根据上一篇内容中…

easypoi 实现word模板导出

特此非常致谢&#xff1a;easypoi实现word模板 基础的可以参考上文&#xff1b; 但是我的需求有一点点不一样。 这是我的模板&#xff1a;就是我的t.imgs 是个list 但是很难过的是easy poi 我弄了一天&#xff0c;我都没有弄出来嵌套list循环怎么输出显示&#xff0c;更难过…

Unity中数据存储_LitJson

文章目录 LitJson一&#xff1a;介绍二&#xff1a;特点三&#xff1a;使用四&#xff1a;注意事项 LitJson 一&#xff1a;介绍 LitJson 是一个专为 .NET 设计的轻量级 JSON 处理库&#xff0c;支持序列化和反序列化 JSON 数据。 二&#xff1a;特点 快速且轻量 无外部依赖…

2025年首届人形机器人半程马拉松比赛(附机器人照片)

2025年4月19日&#xff0c;北京亦庄半程马拉松暨人形机器人半场马拉松正式开赛&#xff0c;作为全球首届人形机器人户外跑步成功举办&#xff0c;21.0975公里的户外路程对人形机器人来讲&#xff0c;注定将成为历史性开篇&#xff0c;如果赛事能够持续举办&#xff0c;那举办意…

网络安全职业技能大赛Server2003

通过本地PC中渗透测试平台Kali对服务器场景Windows进⾏系统服务及版本扫描渗透测 试&#xff0c;并将该操作显示结果中Telnet服务对应的端⼝号作为FLAG提交 使用nmap扫描发现目标靶机开放端口232疑似telnet直接进行连接测试成功 Flag&#xff1a;232 通过本地PC中渗透测试平台…

[java八股文][Java基础面试篇]I/O

Java怎么实现网络IO高并发编程&#xff1f; 可以用 Java NIO &#xff0c;是一种同步非阻塞的I/O模型&#xff0c;也是I/O多路复用的基础。 传统的BIO里面socket.read()&#xff0c;如果TCP RecvBuffer里没有数据&#xff0c;函数会一直阻塞&#xff0c;直到收到数据&#xf…

Python常用的第三方模块之【jieba库】支持三种分词模式:精确模式、全模式和搜索引擎模式(提高召回率)

Jieba 是一个流行的中文分词Python库&#xff0c;它提供了三种分词模式&#xff1a;精确模式、全模式和搜索引擎模式。精确模式尝试将句子最精确地切分&#xff0c;适合文本分析&#xff1b;全模式则扫描文本中所有可能的词语&#xff0c;速度快但存在冗余&#xff1b;搜索引擎…

QT6 源(37):界面组件的总基类 QWidget 的源码阅读(下,c++ 代码部分)

&#xff08;1&#xff09; QT 在 c 的基础上增加了自己的编译器&#xff0c;以支持元对象系统和 UI 界面设计&#xff0c;有 MOC 、 UIC 等 QT 自己的编译器。本节的源代码里&#xff0c;为了减少篇幅&#xff0c;易于阅读&#xff0c;去除了上篇中的属性部分&#xff0c; 上篇…

rabbitmq-spring-boot-start版本优化升级

文章目录 1.前言2.优化升级内容3.依赖4.使用4.1发送消息代码示例4.2消费监听代码示例4.3 brock中的消息 5.RabbmitMq的MessageConverter消息转换器5.1默认行为5.2JDK 序列化的缺点5.3使用 JSON 进行序列化 6.总结 1.前言 由于之前手写了一个好用的rabbitmq-spring-boot-start启…

git lfs下载大文件限额

起因是用 model.load_state_dict(torch.load())加载pt权重文件时&#xff0c;出现错误&#xff1a;_pickle.UnpicklingError: invalid load key, ‘v’. GPT告诉我&#xff1a;你的 pt 文件不是权重文件&#xff0c;而是模型整体保存&#xff08;或根本不是 PyTorch 文件&#…

什么是RAG?RAG的主要流程是什么?

**RAG(Retrieval-Augmented Generation)**是一种结合检索与生成技术的框架,旨在通过引入外部知识增强生成模型的性能。其核心思想是:在生成文本时,先从外部知识库中检索相关信息,再将检索结果与原始输入结合,作为生成模型的输入,从而提升生成内容的准确性、相关性和信息…

【Rust 精进之路之第13篇-生命周期·进阶】省略规则与静态生命周期 (`‘static`)

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025年4月20日 引言:让编译器“读懂”你的意图——省略的艺术 在上一篇【生命周期入门】中,我们理解了生命周期的必要性——它是 Rust 编译器用来确保引用有效性、防止悬垂引用的关键机制。我…

Python爬虫实战:获取xie程网敦煌酒店数据并分析,为51出行做参考

一、引言 伴随互联网的飞速发展,在线旅游平台成为人们出行预订酒店的重要途径。xie程网作为国内颇具知名度的在线旅游平台,存有丰富的酒店信息。借助爬取xie程网的酒店数据并加以深入分析,能够为用户提供更为精准的酒店推荐,特别是在旅游旺季,如 51 出行期间。本研究致力…

第二十一讲 XGBoost 回归建模 + SHAP 可解释性分析(利用R语言内置数据集)

下面我将使用 R 语言内置的 mtcars 数据集&#xff0c;模拟一个完整的 XGBoost 回归建模 SHAP 可解释性分析 实战流程。我们将以预测汽车的油耗&#xff08;mpg&#xff09;为目标变量&#xff0c;构建 XGBoost 模型&#xff0c;并用 SHAP 来解释模型输出。 &#x1f697; 示例…