Vue3 学习笔记(Day5)
「写在前面」
本文为尚硅谷禹神 Vue3 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容:
1. Vue3 学习笔记(Day1)
2. Vue3 学习笔记(Day2)
3. Vue3 学习笔记(Day3)
4. Vue3 学习笔记(Day4)
目录
-
6 组件通信 -
6.1 props -
6.2 自定义事件 -
6.3 mitt -
6.4 v-model -
6.5 $attrs -
6.6 parent -
6.7 provide、inject -
6.8 pinia -
6.9 slot
-
6 组件通信
P52:https://www.bilibili.com/video/BV1Za4y1r7KE?p=52
Vue3组件通信和Vue2的区别:
-
移出事件总线,使用 mitt代替。
-
vuex换成了pinia。 -
把 .sync优化到了v-model里面了。 -
把 $listeners所有的东西,合并到$attrs中了。 -
$children被砍掉了。
常见搭配形式:
6.1 props
概述:props是使用频率最高的一种通信方式,常用与 :父 ↔ 子。
-
若 父传子:属性值是 非函数。 -
若 子传父:属性值是 函数。
父组件:
<template>
<div class="father">
<h3>父组件,</h3>
<h4>我的车:{{ car }}</h4>
<h4>儿子给的玩具:{{ toy }}</h4>
<Child :car="car" :getToy="getToy"/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from './Child.vue'
import { ref } from "vue";
// 数据
const car = ref('奔驰')
const toy = ref()
// 方法
function getToy(value:string){
toy.value = value
}
</script>
子组件
<template>
<div class="child">
<h3>子组件</h3>
<h4>我的玩具:{{ toy }}</h4>
<h4>父给我的车:{{ car }}</h4>
<button @click="getToy(toy)">玩具给父亲</button>
</div>
</template>
<script setup lang="ts" name="Child">
import { ref } from "vue";
const toy = ref('奥特曼')
defineProps(['car','getToy'])
</script>
6.2 自定义事件
P53:https://www.bilibili.com/video/BV1Za4y1r7KE?p=53
-
概述:自定义事件常用于: 子 => 父。 -
注意区分好:原生事件、自定义事件。
-
原生事件: -
事件名是特定的( click、mosueenter等等) -
事件对象 $event: 是包含事件相关信息的对象(pageX、pageY、target、keyCode)
-
-
自定义事件: -
事件名是任意名称 -
事件对象 $event: 是调用emit时所提供的数据,可以是任意类型!!!
-
-
示例:
<!--在父组件中,给子组件绑定自定义事件:-->
<Child @send-toy="toy = $event"/>
<!--注意区分原生事件与自定义事件中的$event-->
<button @click="toy = $event">测试</button>
//子组件中,触发事件:
this.$emit('send-toy', 具体数据)
6.3 mitt
P54:https://www.bilibili.com/video/BV1Za4y1r7KE?p=54
概述:与消息订阅与发布(pubsub)功能类似,可以实现任意组件间通信。
安装mitt
npm i mitt
新建文件:src\utils\emitter.ts
// 引入mitt
import mitt from "mitt";
// 创建emitter
const emitter = mitt()
/*
// 绑定事件
emitter.on('abc',(value)=>{
console.log('abc事件被触发',value)
})
emitter.on('xyz',(value)=>{
console.log('xyz事件被触发',value)
})
setInterval(() => {
// 触发事件
emitter.emit('abc',666)
emitter.emit('xyz',777)
}, 1000);
setTimeout(() => {
// 清理事件
emitter.all.clear()
}, 3000);
*/
// 创建并暴露mitt
export default emitter
接收数据的组件中:绑定事件、同时在销毁前解绑事件:
import emitter from "@/utils/emitter";
import { onUnmounted } from "vue";
// 绑定事件
emitter.on('send-toy',(value)=>{
console.log('send-toy事件被触发',value)
})
onUnmounted(()=>{
// 解绑事件
emitter.off('send-toy')
})
【第三步】:提供数据的组件,在合适的时候触发事件
import emitter from "@/utils/emitter";
function sendToy(){
// 触发事件
emitter.emit('send-toy',toy.value)
}
注意这个重要的内置关系,总线依赖着这个内置关系
6.4 v-model
P55:https://www.bilibili.com/video/BV1Za4y1r7KE?p=55
P56:https://www.bilibili.com/video/BV1Za4y1r7KE?p=56
概述:实现 父↔子 之间相互通信。
前序知识 —— v-model的本质
<!-- 使用v-model指令 -->
<input type="text" v-model="userName">
<!-- v-model的本质是下面这行代码 -->
<input
type="text"
:value="userName"
@input="userName =(<HTMLInputElement>$event.target).value"
>
组件标签上的v-model的本质::moldeValue + update:modelValue事件。
<!-- 组件标签上使用v-model指令 -->
<AtguiguInput v-model="userName"/>
<!-- 组件标签上v-model的本质 -->
<AtguiguInput :modelValue="userName" @update:model-value="userName = $event"/>
AtguiguInput组件中:
<template>
<div class="box">
<!--将接收的value值赋给input元素的value属性,目的是:为了呈现数据 -->
<!--给input元素绑定原生input事件,触发input事件时,进而触发update:model-value事件-->
<input
type="text"
:value="modelValue"
@input="emit('update:model-value',$event.target.value)"
>
</div>
</template>
<script setup lang="ts" name="AtguiguInput">
// 接收props
defineProps(['modelValue'])
// 声明事件
const emit = defineEmits(['update:model-value'])
</script>
也可以更换value,例如改成abc
<!-- 也可以更换value,例如改成abc-->
<AtguiguInput v-model:abc="userName"/>
<!-- 上面代码的本质如下 -->
<AtguiguInput :abc="userName" @update:abc="userName = $event"/>
AtguiguInput组件中:
<template>
<div class="box">
<input
type="text"
:value="abc"
@input="emit('update:abc',$event.target.value)"
>
</div>
</template>
<script setup lang="ts" name="AtguiguInput">
// 接收props
defineProps(['abc'])
// 声明事件
const emit = defineEmits(['update:abc'])
</script>
如果value可以更换,那么就可以在组件标签上多次使用v-model
<AtguiguInput v-model:abc="userName" v-model:xyz="password"/>
6.5 $attrs
P57:https://www.bilibili.com/video/BV1Za4y1r7KE?p=57
概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。
具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。
注意:$attrs会自动排除props中声明的属性(可以认为声明过的 props 被子组件自己“消费”了)
父组件:
<template>
<div class="father">
<h3>父组件</h3>
<Child :a="a" :b="b" :c="c" :d="d" v-bind="{x:100,y:200}" :updateA="updateA"/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from './Child.vue'
import { ref } from "vue";
let a = ref(1)
let b = ref(2)
let c = ref(3)
let d = ref(4)
function updateA(value){
a.value = value
}
</script>
子组件:
<template>
<div class="child">
<h3>子组件</h3>
<GrandChild v-bind="$attrs"/>
</div>
</template>
<script setup lang="ts" name="Child">
import GrandChild from './GrandChild.vue'
</script>
孙组件:
<template>
<div class="grand-child">
<h3>孙组件</h3>
<h4>a:{{ a }}</h4>
<h4>b:{{ b }}</h4>
<h4>c:{{ c }}</h4>
<h4>d:{{ d }}</h4>
<h4>x:{{ x }}</h4>
<h4>y:{{ y }}</h4>
<button @click="updateA(666)">点我更新A</button>
</div>
</template>
<script setup lang="ts" name="GrandChild">
defineProps(['a','b','c','d','x','y','updateA'])
</script>
6.6 $refs、$parent
P58:https://www.bilibili.com/video/BV1Za4y1r7KE?p=58
P59:https://www.bilibili.com/video/BV1Za4y1r7KE?p=59
概述:
-
$refs用于 : 父→子。 -
$parent用于: 子→父。
原理如下:
| 属性 | 说明 |
|---|---|
$refs | 值为对象,包含所有被ref属性标识的DOM元素或组件实例。 |
$parent | 值为对象,当前组件的父组件实例对象。 |
6.7 provide、inject
P60:https://www.bilibili.com/video/BV1Za4y1r7KE?p=60
概述:实现祖孙组件直接通信
具体使用:
-
在祖先组件中通过 provide配置向后代组件提供数据 -
在后代组件中通过 inject配置来声明接收数据
具体编码:
【第一步】父组件中,使用provide提供数据
<template>
<div class="father">
<h3>父组件</h3>
<h4>资产:{{ money }}</h4>
<h4>汽车:{{ car }}</h4>
<button @click="money += 1">资产+1</button>
<button @click="car.price += 1">汽车价格+1</button>
<Child/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from './Child.vue'
import { ref,reactive,provide } from "vue";
// 数据
let money = ref(100)
let car = reactive({
brand:'奔驰',
price:100
})
// 用于更新money的方法
function updateMoney(value:number){
money.value += value
}
// 提供数据
provide('moneyContext',{money,updateMoney})
provide('car',car)
</script>
【第二步】孙组件中使用inject配置项接受数据
<template>
<div class="grand-child">
<h3>我是孙组件</h3>
<h4>资产:{{ money }}</h4>
<h4>汽车:{{ car }}</h4>
<button @click="updateMoney(6)">点我</button>
</div>
</template>
<script setup lang="ts" name="GrandChild">
import { inject } from 'vue';
// 注入数据
let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(x:number)=>{}})
let car = inject('car')
</script>
6.8 pinia
参考之前pinia部分的讲解
6.9 slot
1. 默认插槽
P61:https://www.bilibili.com/video/BV1Za4y1r7KE?p=61
父组件中:
<Category title="今日热门游戏">
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
</Category>
子组件中:
<template>
<div class="item">
<h3>{{ title }}</h3>
<!-- 默认插槽 -->
<slot></slot>
</div>
</template>
2. 具名插槽
P62:https://www.bilibili.com/video/BV1Za4y1r7KE?p=62
父组件中:
<Category title="今日热门游戏">
<template v-slot:s1>
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
</template>
<template #s2>
<a href="">更多</a>
</template>
</Category>
子组件中:
<template>
<div class="item">
<h3>{{ title }}</h3>
<slot name="s1"></slot>
<slot name="s2"></slot>
</div>
</template>
3. 作用域插槽
P63:https://www.bilibili.com/video/BV1Za4y1r7KE?p=63
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(新闻数据在News组件中,但使用数据所遍历出来的结构由App组件决定)
父组件中:
<Game v-slot="params">
<!-- <Game v-slot:default="params"> -->
<!-- <Game #default="params"> -->
<ul>
<li v-for="g in params.games" :key="g.id">{{ g.name }}</li>
</ul>
</Game>
子组件中:
<template>
<div class="category">
<h2>今日游戏榜单</h2>
<slot :games="games" a="哈哈"></slot>
</div>
</template>
<script setup lang="ts" name="Category">
import {reactive} from 'vue'
let games = reactive([
{id:'asgdytsa01',name:'英雄联盟'},
{id:'asgdytsa02',name:'王者荣耀'},
{id:'asgdytsa03',name:'红色警戒'},
{id:'asgdytsa04',name:'斗罗大陆'}
])
</script>
本文由 mdnice 多平台发布
相关文章:
Vue3 学习笔记(Day5)
「写在前面」 本文为尚硅谷禹神 Vue3 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容: 1. Vue3 学习笔记(Day1) 2. Vue3 学习笔记(Day2&…...
【网络编程】实现服务器端和客户端的通讯的简单程序
套接字是什么? 服务端接受连接请求的套接字创建过程可分为以下4步: 1、调用socket创建套接字 2、调用bind函数分配IP地址和端口号 3、调用listen函数转换为可接受请求状态 4、调用accept函数受理连接请求 1、调用socket创建套接字 serv_sock soc…...
如何在Portainer中部署Nginx容器并制作一个本地站点结合cpolar发布至公网可访问
文章目录 前言1. 安装Portainer1.1 访问Portainer Web界面 2. 使用Portainer创建Nginx容器3. 将Web静态站点实现公网访问4. 配置Web站点公网访问地址4.1公网访问Web站点 5. 固定Web静态站点公网地址6. 固定公网地址访问Web静态站点 前言 Portainer是一个开源的Docker轻量级可视…...
Mysql的储存引擎
储存引擎介绍 1. 文件系统 操作系统存取数据的一种机制 2. 文件系统类型 不管使用什么文件系统,数据内容不会变化 不同的是,存储空间、大小、速度 3. MySQL存储引擎 可以理解为,MySQL的“文件系统”,只不过功能更加强大 4. MySQL…...
【查漏补缺你的Vue基础】Vue数据监听深度解析
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
大语言模型LLM发展历程中的里程碑项目:国内外技术革新重塑自然语言处理(LLM系列02)
文章目录 标题:大语言模型LLM发展历程中的里程碑项目:国内外技术革新重塑自然语言处理(LLM系列02) 引言早期奠基阶段Transformer架构引领变革GPT系列的重大进展国内外标志性LLM项目LLM在中国的应用实践LLM研究面临的挑战与应对策略…...
JS二进制文件转换:File、Blob、Base64、ArrayBuffer
类型转换 1. Blob、File → Base64 function fileToDataURL(file) {let reader new FileReader();reader.readAsDataURL(file);reader.onload function (e) {return reader.result;}; }2. Base64 → Blob、File // Base64 转为 Blob function dataURLToBlob(fileDataURL) …...
编译opencv gpu版的条件
一、具备以下条件即可编译opencv gpu: 1、 终端设备必须有独立显卡。cmd窗口:nvidia-smi查看显卡信息 2、下载并安装CUDA Toolkit(根据显卡下载对应的CUDA Toolkit软件)、cuDNN(根据CUDA版本下载对应的cuDNN࿰…...
List集合的Stream流式操作实现数据类型转换
问题现象: 最近在项目中,有一些逻辑想用List集合的Stream流式操作来快速实现,但由于之前没做好学习笔记和总结,导致一时间想不起来,只能用本方法来解决,如下: 可以看出来代码量是比较冗长的&…...
Ubuntu 20.04.6 LTS下edge浏览器点击图标没反应
1.网上的解决方案 解决Ubuntu系统下启动root账户后Linux版本edge浏览器无法启动等 2.采用的解决方案 之前我一直是在官网下载 Microsoft Edge下载,安装,卸载,重装的stable版本,然后安装,始终没有效果。 最后利用Linux…...
php基础学习之错误处理(其一)
一,错误处理的概念 错误处理指的是系统(或者用户)在执行某些代码的时候,发现有错误,就会通过错误处理的形式告知程序员,俗称报错 二,错误分类 语法错误:书写的代码不符合 PHP 的语法规范,语法错…...
Nginx 解析漏洞复现
环境搭建 下载之后上传到虚拟机并解压 进入这个路径 (root?kali)-[~/vulhub-master/nginx/nginx_parsing_vulnerability]就能看到有docker-compose.yml 启动环境 正常显示 增加/.php后缀,被解析成PHP文件: 漏洞原因:开启了cgi.fix_pathin…...
JQMobile Loader Widget 遮罩层改造
最近在用jqmobile 做一个混合APP项目时候用到 jqmobile1.4.3提供的Loader Widget控件,但是这个控件本身是一个loading弹出层,这个弹出层弹出之后,用户还是可以去点击按钮,重复发送请求,为了防止重复提交,我想了两种办法, 1,在loading弹出层弹出之后,让按钮不可用.但是form表单…...
练习 2 Web [ACTF2020 新生赛]BackupFile 1
[ACTF2020 新生赛]BackupFile 1 Web常规题目 首先尝试查找常见的前端页面index.php之类的,没找到 题目有个“BackupFile”——备份文件 尝试用工具遍历查找相关的文件 御剑没扫出来,搜索搭建好dirsearch后,扫出来的index.php.bak 扫描工…...
【python】subprocess用法示例
当然,下面是一些使用 Python subprocess 模块的示例: 1. 运行命令并捕获输出 import subprocess # 运行 ls 命令并捕获输出 result subprocess.run([ls, -l], stdoutsubprocess.PIPE, stderrsubprocess.PIPE, textTrue) # 获取命令的输出和错误信息 o…...
Socket网络编程(三)——TCP快速入门
目录 概述TCP连接可靠性1. 三次握手过程2. 四次挥手过程3. 为什么挥手需要四次? 传输可靠性TCP核心APITCP传输初始化配置&建立连接客户端创建Socket建立连接服务端创建ServerSocket监听连接ServerSocket 和 Socket的关系 Socket基本数据类型传输客户端数据传输服…...
皇冠测评:网络电视盒子哪个品牌好?电视盒子排行榜
欢迎各位来到我们的测评频道,本期我们要分享的产品是电视盒子,因很多网友留言不知道网络电视盒子哪个品牌好,我们通过为期一个月的测评后整理了电视盒子排行榜,想买电视盒子的可以看看下面这五款产品,它们各方面表现非…...
simple-pytest 框架使用指南
simple-pytest 框架使用指南 一、框架介绍简介框架理念:框架地址 二、实现功能三、目录结构四、依赖库五、启动方式六、使用教程1、快速开始1.1、创建用例:1.2、生成py文件1.3、运行脚本1.3.1 单个脚本运行1.3.2 全部运行 1.4 报告查看 2、功能介绍2.1、…...
React中使用useActive
1.引入 import { useActivate } from "react-activation";2.React Activation 在React中使用react-activation,其实就是类似于Vue中的keep-alive,实现数据的缓存; 源码: import { ReactNode, ReactNodeArray, Context, Component…...
ElasticSearch安装和kibana控制台安装
文章目录 简介ElasticSearch安装环境下载参数密码配置启动 kibana安装修改config/kibana.yml配置 简介 Elasticsearch 是一个分布式文档存储。Elasticsearch 是存储已序列化为 JSON 文档的复杂数据结构。当集群中有多个 Elasticsearch 节点时,存储的文档分布在整个…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...
【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
