vue3组件通信学习笔记

1、Prop

父组件

<template><div class="parent"><h1>我是父元素</h1><Child :msg="msg"></Child></div>
</template><script setup>
import Child from './Child.vue'
let msg = ref('我是父组件的数据')
</script><style scoped>
.parent{width: 800px;height: 600px;background: skyblue;
}
</style>

子组件

<template><div class="son"><h3>我是子元素</h3><h4>{{ msg }}</h4></div>
</template><script setup>
// 1、let props = defineProps(['msg'])
//2、defineProps(['msg'])
//3、
defineProps({msg:{type:String,default:'默认数据'}
})
</script><style scoped>
.son{width: 200px;height: 200px;background: pink;
}
</style>

在这里插入图片描述

2、自定义事件

父组件

<template><div class="parent"><h1>我是父元素</h1><Child :msg="msg" @getData="getData"></Child><hr><p>父组件接收数据:{{passStr}}</p></div>
</template><script setup>
import Child from './Child.vue'
let msg = ref('我是父组件的数据');
let passStr = ref('')
const getData = (e)=>{passStr.value=e
}
</script><style scoped>
.parent{width: 800px;height: 600px;background: skyblue;
}
</style>

子组件

<template><div class="son"><h3>我是子元素</h3><h4>{{ msg }}</h4><button @click="passData('我是子组件数据')">给父组件传递参数</button></div>
</template><script setup>
// 1、let props = defineProps(['msg'])
//2、defineProps(['msg'])
//3、
defineProps({msg:{type:String,default:'默认数据'}
})
let $emit = defineEmits('getData')
const passData = (msg)=>{$emit('getData',msg)
}
</script><style scoped>
.son{width: 200px;height: 200px;background: pink;
}
</style>

在这里插入图片描述

3、全局事件总线

1、安装

npm install --save mitt

2、新建utils/mitt.js

import mitt from 'mitt'const emitter =new mitt()export default emitter

3、使用

子组件1

<template><div class="son"><h3>我是子元素</h3><h4>{{ msg }}</h4><button @click="passData('我是子组件数据')">给父组件传递参数</button><button @click="passBusData('我是子组件1的数据')">给子组件2传递参数</button></div>
</template><script setup>
import emitter from '../utils/mitt'
// 1、let props = defineProps(['msg'])
//2、defineProps(['msg'])
//3、
defineProps({msg:{type:String,default:'默认数据'}
})
let $emit = defineEmits('getData')
const passData = (msg)=>{$emit('getData',msg)
}
const instance = getCurrentInstance()
const passBusData = (msg) =>{emitter.emit("passBusData",msg)
}
</script><style scoped>
.son{width: 200px;height: 200px;background: pink;
}
</style>

子组件2

<template><div class="child1"><h3>子组件2</h3><p>{{msg}}</p></div>
</template><script setup>
import emitter from '../utils/mitt'
let msg = ref('')
onMounted(() => {emitter.on("passBusData",(data) =>{msg.value=data})
});
</script><style  scoped>
.child1{width: 200px;height: 200px;background: hotpink;
}
</style>

在这里插入图片描述

4、v-model

1、绑定单个数据

父组件

<template><div class="parent"><h1>父组件钱数:{{money}}</h1><input type="number" v-model="money"><!-- props:父组件给子组件传值 --><!-- <Child :modelValue="money" @update:modelValue="getData" /> --><!-- v-model组件身上使用1、相当于给子组件传递props[modelValue] = 10002、给子组件绑定自定义事件update:modelValue--><Child v-model="money" /></div>
</template><script setup>
import Child from './Child.vue';
import { ref } from 'vue';
// v-model 指令 收集表单数据,双向数据绑定
// v-model也可以实现组件之间通信,实现父子组件数据同步
// 父组件给子组件传数据 props
// 子组件给父组件传数据 自定义事件
let money = ref(1000);
const getData = (data)=>{money.value = data
}
</script><style lang="scss" scoped>
.parent{width:800px;height:500px;background: pink;
}
</style>

子组件

<template><div class="child"><h3>子组件接收父组件钱数{{modelValue}}</h3><button @click="handler">子组件改变数据</button></div>
</template><script setup>
let props = defineProps(['modelValue']);
let emits = defineEmits(['update:modelValue']);
const handler = () => {emits('update:modelValue',props.modelValue+100)
}
</script><style lang="scss" scoped>
.child{width: 300px;height: 200px;background: skyblue;
}
</style>

在这里插入图片描述

2、绑定多个数据

父组件

<template><div class="parent"><h2>父组件钱数:{{money}}当前页{{currentPage}}每页条数{{pageSize}}</h2><input type="number" v-model="money"><!-- props:父组件给子组件传值 --><!-- <Child :modelValue="money" @update:modelValue="getData" /> --><!-- v-model组件身上使用1、相当于给子组件传递props[modelValue] = 10002、给子组件绑定自定义事件update:modelValue--><Child v-model="money" /><Child2 v-model:currentPage="currentPage" v-model:pageSize="pageSize"></Child2></div>
</template><script setup>
import Child from './Child.vue';
import Child2 from './Child2.vue';
import { ref } from 'vue';
// v-model 指令 收集表单数据,双向数据绑定
// v-model也可以实现组件之间通信,实现父子组件数据同步
// 父组件给子组件传数据 props
// 子组件给父组件传数据 自定义事件
let money = ref(1000);
const getData = (data)=>{money.value = data
}
//
let currentPage =ref(1)
let pageSize =ref(20)
</script><style lang="scss" scoped>
.parent{width:800px;height:600px;background: pink;
}
</style>

子组件

<template><div class="child2"><h3>子组件2接收父组传递的数据{{currentPage}}{{ pageSize }}</h3><button @click="emits('update:currentPage',currentPage+1)">改变父组件currentPage</button><button @click="emits('update:pageSize',pageSize+10)">改变父组件pageSize</button></div>
</template><script setup>
let props=defineProps(['currentPage','pageSize'])
let emits= defineEmits(['update:currentPage','update:pageSize'])
</script><style lang="scss" scoped>
.child2{width:300px;height:200px;background: hotpink;
}
</style>

在这里插入图片描述

5、useAttr

父组件

<template><div class="parent"><h2>父组件</h2><Child type="primary" title="编辑按钮" size="small" @click="handler" /></div>
</template><script setup>
import Child from './Child.vue';
const handler = ()=>{alert('点击了')
}
</script><style lang="scss" scoped>
.parent{width:800px;height:600px;background: pink;
}
</style>

子组件

<template><div class="child"><h3>子组件</h3><!-- <el-button :type="$attrs.type" :size="$attrs.size">按钮</el-button> --><el-button :="$attrs">按钮</el-button></div>
</template><script setup>
//引入useAttrs方法:获取组件标签身上属性与事件
let $attrs = useAttrs()let props= defineProps(['title'])
console.log(props)
console.log($attrs)
//props和useAttrs方法都可以获取父组件传过来的属性和属性值
//但是props接收了useAttrs方法就获取不到了
</script><style lang="scss" scoped>
.child{width: 300px;height: 200px;background: skyblue;
}
</style>

在这里插入图片描述

6、ref与$parent

父组件

<template><div class="parent"><h2>父组件钱数:{{money}}</h2><button @click="borrowMoney">向子组件借100</button><Child ref="child" /></div>
</template><script setup>
import Child from './Child.vue';
// ref可以获取真实的DOM节点,可以获取到组件真实VC
//$parent 可以在子组件内部获取父组件的实例
let money = ref(1000)//向外暴露
defineExpose({money
})
//获取子组件实例
let child = ref();//借钱
let borrowMoney = ()=>{money.value+=100;child.value.money-=100;//child.value.handler()
}
</script><style lang="scss" scoped>
.parent{width:800px;height:600px;background: pink;
}
</style>

子组件

<template><div class="child"><h3>子组件钱数:{{money}}</h3><button @click="handler($parent)">向父组件借钱100</button></div>
</template><script setup>
let money = ref(1000)
//组件内部的数据是对外关闭的,别人不能访问
//如果想让外部访问需要通过defineExpose方法对外暴露
let handler = ($parent)=>{console.log('子组件事件');money.value+=100;$parent.money-=100
}
defineExpose({money,handler
})
</script><style lang="scss" scoped>
.child{width: 300px;height: 200px;background: skyblue;
}
</style>

在这里插入图片描述

7、Provide与Inject

父组件

<template><div class="parent"><h2>父组件数据:{{car}}</h2><Child ref="child" /></div>
</template><script setup>
import Child from './Child.vue';
//vue3提供provide(提供)与inject(注入)可以实现隔辈组件传递数据
let car = ref('法拉利');
//祖先组件给后代组件传递数据
//两个参数,第一个参数是提供数据的数据key
//第二个参数 祖先组件提供的数据
provide('car', car);
</script><style lang="scss" scoped>
.parent{width:800px;height:600px;background: pink;
}
</style>

子组件

<template><div class="child"><h3>子组件</h3><Grandson></Grandson></div>
</template><script setup>
import Grandson from './Grandson.vue';
</script><style lang="scss" scoped>
.child{width: 300px;height: 200px;background: skyblue;
}
</style>

孙子组件

<template><div class="grandson"><h5>孙子组件接收祖先组件传递的数据:{{car}}</h5><button @click="updateData">更改祖先组件数据</button></div>
</template><script setup>
//注入祖先组件提供的数据
//需要参数:即为祖先组件提供数据的key
let car = inject("car");
let updateData = ()=>{car.value='宝马'
}
</script><style lang="scss" scoped>
.grandson{width:200px;height: 100px;background: yellowgreen;
}
</style>

在这里插入图片描述

8、pinia

1、安装

pnpm i pinia

2、在src文件夹下创建store文件夹,新建index.js

//创建大仓库
import { createPinia } from 'pinia';
//createPinia方法可以用来创建大仓库
let store = createPinia();
//对外暴露,安装仓库
export default store

3、在main.js中引入使用

//引入仓库
import store from './store'
let app= createApp(App);app.use(store).mount('#app')

4、在store文件夹下新建modules文件夹,新建info.js

1、选择式写法

1、info.js

//定义info小仓库
import { defineStore } from "pinia";//2个参数:1、小仓库名称 2小仓库配置对象
//defineStore方法执行返回一个函数,函数作用让组件获取到仓库数据
let useInfoStore = defineStore("info",{//存储数据 statestate: ()=>{return {count:99,arr:[1,2,3,4,5,6,7,8,9,10]}},actions:{updateCount(num){// this.count++this.count+=num;}},getters:{total(){return this.arr.reduce((pre,next)=>{return pre+next},0)}}
})//对外暴露
export default useInfoStore;

2、在组件1中使用

<template><div class="child"><h3>子组件-接收仓库数据:{{infoStore.count}}</h3><h4>getters:数组求和:{{infoStore.total}}</h4><button @click="updateCount">修改仓库数据</button></div>
</template><script setup>
import useInfoStore from '../store/modules/info';
//获取小仓库对象
let infoStore = useInfoStore();
console.log(infoStore)
//修改仓库数据
let updateCount = ()=>{//1、直接修改//infoStore.count++//2、patch// infoStore.$patch({//     count:100// })//3、调用store方法infoStore.updateCount(10)
}
</script><style lang="scss" scoped>
.child{width: 300px;height: 200px;background: skyblue;
}
</style>

3、在组件2中使用

<template><div class="child2"><h3>子组件2-接收仓库数据:{{infoStore.count}}</h3></div>
</template><script setup>
import useInfoStore from '../store/modules/info';
//获取小仓库对象
let infoStore = useInfoStore();</script><style lang="scss" scoped>
.child2{width:300px;height:200px;background: hotpink;
}
</style>

在这里插入图片描述

2、组合式API写法

1、在modules文件夹下新建todo.js

//定义组合式API
import { defineStore } from "pinia";
import { ref , computed } from 'vue'
//创建小仓库
let useTodoStore = defineStore('todo',()=>{//务必返回一个对象,对象的属性和方法提供给组件使用let todos = ref([{id:1,title:'吃饭'},{id:2,title:'睡觉'},{id:3,title:'打豆豆'},])let arr=ref([1,2,3,4,5])const total = computed(()=>{return arr.value.reduce((prev, curr) => {return prev+curr}, 0)})return {todos,//相当于选择式API的statearr,total,updateTodos(){todos.value.push({id:4,title:'摆烂'})},//相当于选择式API的actions}})export default useTodoStore

2、在组件1中使用

<template><div class="child"><h3>子组件-接收仓库数据:</h3><ul><li v-for="item in todosStore.todos" :key="item.id">{{item.title}}</li></ul><p>{{ todosStore.arr }}--总和{{todosStore.total}}</p><button @click="updateTodos">修改仓库数据</button></div>
</template><script setup>
//引入组合式API函数仓库
import useTodosStore from '../store/modules/todo';
let todosStore = useTodosStore();
//修改仓库数据
let updateTodos = ()=>{todosStore.updateTodos()
}
</script><style lang="scss" scoped>
.child{width: 300px;height: 300px;background: skyblue;
}
</style>

3、在组件2中使用

<template><div class="child2"><h3>子组件2-接收仓库数据:</h3><ul><li v-for="item in todosStore.todos" :key="item.id">{{item.title}}</li></ul></div>
</template><script setup>
import useTodosStore from '../store/modules/todo';
//获取小仓库对象
let todosStore = useTodosStore();</script><style lang="scss" scoped>
.child2{width:300px;height:300px;background: hotpink;
}
</style>

在这里插入图片描述

9、slot

1、默认插槽

父组件

<template><div class="parent"><h2>父组件</h2><div class="container"><Child><pre>我是父组件传入的数据</pre></Child></div></div>
</template><script setup>
import Child from './Child.vue';
//插槽:默认插槽、具名插槽、作用域插槽
</script><style lang="scss" scoped>
.parent{width:800px;height:400px;background: pink;.container{display: flex;align-items: center;justify-content: space-around;}
}
</style>

子组件

<template><div class="child"><h3>我是子组件默认插槽</h3><!-- 默认插销 --><slot></slot><h3>我是子组件默认插槽</h3></div>
</template><script setup>
//引入组合式API函数仓库
import useTodosStore from '../store/modules/todo';
let todosStore = useTodosStore();
//修改仓库数据
let updateTodos = ()=>{todosStore.updateTodos()
}
</script><style lang="scss" scoped>
.child{width: 300px;height: 300px;background: skyblue;
}
</style>

在这里插入图片描述

2、具名插槽

父组件

<template><div class="parent"><h2>父组件</h2><div class="container"><Child><!-- 具名插槽填充 v-slot:简写问# --><template v-slot:a><p>我是填充具名插槽a位置结构</p></template><template #b><p>我是填充具名插槽b位置结构</p></template></Child></div></div>
</template><script setup>
import Child from './Child.vue';
//插槽:默认插槽、具名插槽、作用域插槽
</script><style lang="scss" scoped>
.parent{width:800px;height:400px;background: pink;.container{display: flex;align-items: center;justify-content: space-around;}
}
</style>

子组件

<template><div class="child"><h3>我是子组件具名插槽</h3><slot name="a"></slot><h3>我是子组件具名插槽</h3><hr><h3>我是子组件具名插槽</h3><slot name="b"></slot><h3>我是子组件具名插槽</h3></div>
</template><script setup>
//引入组合式API函数仓库
import useTodosStore from '../store/modules/todo';
let todosStore = useTodosStore();
//修改仓库数据
let updateTodos = ()=>{todosStore.updateTodos()
}
</script><style lang="scss" scoped>
.child{width: 300px;height: 300px;background: skyblue;
}
</style>

3、作用域插槽

父组件

<template><div class="parent"><h2>父组件</h2><div class="container"><Child :todos="todos"><template v-slot="{$row,$index}"><span :style="{color:$row.done?'green':'red'}">{{ $row.title }}--下标{{$index}}</span></template></Child></div></div>
</template><script setup>
import Child from './Child.vue';
// import Child2 from './Child2.vue';
//插槽:默认插槽、具名插槽、作用域插槽
//作用域插槽:就是可以传递数据的插槽,子组件可以将数据回传给父组件,
//父组件可以决定这些回传的数据是以何种结构或者外观在子组件内部去展示
let todos = ref([{id:1,title:'吃饭',done:true},{id:2,title:'睡觉',done:false},{id:3,title:'打豆豆',done:true},{id:4,title:'打游戏',done:false},
])
</script><style lang="scss" scoped>
.parent{width:800px;height:400px;background: pink;.container{display: flex;align-items: center;justify-content: space-around;}
}
</style>

子组件

<template><div class="child"><h3>子组件1</h3><ul><li v-for="(item,index) in todos" :key="item.id"><!-- 作用域插槽:可以将数据回传给父组件 --><slot :$row="item" :$index="index"></slot></li></ul></div>
</template><script setup>
let props = defineProps(['todos'])
</script><style lang="scss" scoped>
.child{width: 500px;height: 300px;background: skyblue;
}
</style>

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

逆向工程-架构真题(二十)

结构化程序设计采用自顶向下、逐步求精及模块化程序设计方法&#xff0c;通过&#xff08;&#xff09;三种基本控制结构可以构造出任何单入口单出口程序。 顺序、选择和嵌套顺序、分支和循环分支、并发和循环跳转、选择和并发 答案&#xff1a;B 解析&#xff1a; 结构化设…

循环(while do...while for)介绍

3.循环 1.while循环 while循环是先判断后执行 while循环一般都会有: 循环初始值, 循环条件 和 循环变量增量(或者减量) 语法: while(表达式){逻辑代码块 }// 计算123...100之和var num 1;//循环初始值var sum 0;//统计结果//循环条件while (num < 100) {console.log(n…

Element UI实现每次只弹出一个Message消息提示

前言 在开发Web应用程序时&#xff0c;我们经常需要使用消息提示来向用户展示重要信息。Element UI提供了一个方便易用的组件——Message&#xff0c;可以用于显示各种类型的消息提示。 然而&#xff0c;默认情况下&#xff0c;当多个消息提示同时触发时&#xff0c;它们会依…

【MySQL】表的增删改查(进阶)

表的增删改查&#xff08;进阶&#xff09; 一. 数据库约束1. 约束类型2. NULL约束3. UNIQUE&#xff1a;唯一约束4. DEFAULT&#xff1a;默认值约束5. PRIMARY KEY&#xff1a;主键约束6. FOREIGN KEY&#xff1a;外键约束7. CHECK约束 二. 表的设计1. 一对一2. 一对多3. 多对…

坚守低价理念 BSN官方算力中心接口化NFT合约正式上线

为了进一步降低平台方用户的使用成本&#xff0c;同时也为了让平台方用户能够更加便利地使用BSN-DDC基础网络&#xff08;以下简称DDC网络&#xff09;&#xff0c;BSN于日前在官方算力中心门户内正式上线了BSN官方算力中心接口化NFT合约。平台方用户通过该合约执行的NFT铸造、…

JAVA设计模式详解 解构设计模式思想 详细代码对比

JAVA设计模式详解 1 简单工厂模式 1 简单工厂模式 设计模式-01简单工厂模式详解 详细代码对比

对象存储 OSS

大家好 , 我是苏麟 , 今天聊聊OSS . 这里使用阿里云的OSS对象存储. 首先大家得有一个阿里云账号 , 注册大家都会 这里不多介绍 . 阿里云官网 : 阿里云登录页 (aliyun.com) 首页产品目录下存储集合里对象存储OSS 进入对象存储OSS页面 点击管理控制台(新用户应该有免费试用期的)…

huggingface 使用入门笔记

概念 Hugging Face Hub​​和 Github 类似&#xff0c;都是Hub(社区)。Hugging Face可以说的上是机器学习界的Github。Hugging Face为用户提供了以下主要功能&#xff1a; ​模型仓库&#xff08;Model Repository&#xff09;​​&#xff1a;Git仓库可以让你管理代码版本、…

CATIA Composer软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 CATIA&#xff08;Computer-Aided Three-dimensional Interactive Application&#xff09;是一款由法国达索系统公司开发的三维计算机辅助设计&#xff08;CAD&#xff09;软件。它是一种全面的产品开发解决方案&#xff0c;广泛…

docker save docker export 区别

docker save用于导出镜像到文件&#xff0c;包含镜像元数据和历史信息&#xff1b;docker export用于将当前容器状态导出至文件&#xff0c;类似快照&#xff0c;所以不包含元数据及历史信息&#xff0c;体积更小&#xff0c;此外从容器快照导入时也可以重新指定标签和元数据信…

Redis-1.4-过期策略

1 设置带过期时间的 key # 时间复杂度&#xff1a;O&#xff08;1&#xff09;&#xff0c;最常用方式 expire key seconds# 字符串独有方式 setex(String key, int seconds, String value)除了string独有设置过期时间的方法&#xff0c;其他类型都需依靠expire方法设置时间&a…

Flink算子如何限流

目录 使用方法 调用类图 内部源码 GuavaFlinkConnectorRateLimiter RateLimiter 使用方法 重写AbstractRichFunction中的open()方法,在处理数据前调用limiter.acquire(1); 调用limiter.open(getRuntimeContext())的源码,实际内部是RateLimiter,根据并行度算出subTask…

TCP IP网络编程(四) 基于TCP的服务器端、客户端

文章目录 理解TCP、UDPTCP/IP协议栈链路层IP层TCP/UDP层应用层 实现基于TCP的服务器端、客户端TCP服务器端的默认函数调用顺序进入等待连接请求状态受理客户端连接请求TCP客户端的默认函数调用顺序基于TCP的服务器端、客户端函数调用关系 实现迭代服务器端、客户端实现迭代服务…

Java File类和IO流

1. File类 1.1 File对象创建 注意&#xff1a; 路径中"\"要写成"\\"&#xff0c; 路径中"/"可以直接用 File对象可以指代一个不存在的文件路径路径中带盘符是绝对路径&#xff0c;不带盘符是相对路径 1.2 File判断和获取方法 1.3 创建和删除方…

GitHubGiteeGitlab极狐(JihuLab)配置SSH公私钥详细过程

GitHub-微软-github.com Gitee-开源中国- gitee.com Gitlab-乌克兰GitLab 公司-gitlab.com 极狐(JihuLab)-中国代理商运营的Gitlab -gitlab.cn或者jihulab.com 一、生成SSH公钥和私钥 1.1 取消全局设置 $ git config --global user.name "你的名字" $ git confi…

【STM32】FSMC接口的复用和非复用

问题背景 在阅读《零死角玩转STM32—F103指南者》&#xff0c;以及《STM32F10x-中文参考手册》关于FSMC一章节的时候&#xff0c;对于在控制NOR/SRAM的时候使用到的引脚,在提到NOR器件的时候提到了地址复用和非复用接口&#xff0c;一时间没明白是什么东西。 结论 非复用模式…

本专栏的订阅说明、导航直达

&#xff08;1&#xff09;为什么成了付费专栏&#xff1f; 知识付费时代&#xff0c;多做一些尝试免费内容非常容易被其他网站爬虫获取&#xff0c;付费是某种意义上的版权保护付费即意味着责任&#xff0c;有利于提高专栏质量&#xff0c;驱使作者对读者、对内容更负责 &…

IMAU鸿蒙北向开发-2023年9月5日学习日志

1. 5种调试方式 1.1 Previewer 在侧边 Previewer 选项卡内可以预览Entry。 如果要单独预览组件&#xff0c;可以在给组件加Preview 装饰器 1.2 Local Emulator&#xff08;本地模拟&#xff09; 1.3 Remote Emulator&#xff08;远程模拟&#xff09; 使用时需要登录华为开发…

业务安全及实战案例

业务安全 关于漏洞&#xff1a; 注入业务逻辑信息泄露 A04:2021 – Insecure Design 在线靶场PortSwigger 1. 概述 1.1 业务安全现状 1.1.1 业务逻辑漏洞 ​ 近年来&#xff0c;随着信息化技术的迅速发展和全球一体化进程的不断加快&#xff0c;计算机和网络已经成为与…

前端面试题

文章目录 前言一、lodash.get方法&#xff1f;二、实现一个EventEmitter.js三、渲染VNode.js四、设计一个Cache.js 前言 本文主要记录在面试过程中&#xff0c;所遇到的题目。 一、lodash.get方法&#xff1f; 问题&#xff1a; object (Object): 要检索的对象。 path (string…