vue3组件通信方式一

2023-11-12

目录

props

父组件给子组件传递数据

子组件获取父组件传递数据:方式1 

子组件获取父组件传递数据:方式2 

案例

自定义事件

原生DOM事件

自定义事件

案例

全局事件总线

v-model

useAttrs


不管是vue2还是vue3,组件通信方式很重要,不管是项目还是面试都是经常用到的知识点。

比如:vue2组件通信方式

  • **props:**可以实现父子组件、子父组件、甚至兄弟组件通信
  • 自定义事件:可以实现子父组件通信
  • 全局事件总线$bus:可以实现任意组件通信
  • **pubsub:**发布订阅模式实现任意组件通信
  • vuex:集中式状态管理容器,实现任意组件通信
  • ref:父组件获取子组件实例VC,获取子组件的响应式数据以及方法
  • **slot:**插槽(默认插槽、具名插槽、作用域插槽)实现父子组件通信........

props

子组件获取到props数据就可以在模板中使用了,但是切记props是只读的(只能读取,不能修改)

父组件给子组件传递数据

<Child info="我爱祖国" :money="money"></Child>

子组件获取父组件传递数据:方式1 

let props = defineProps({
  info:{
   type:String,//接受的数据类型
   default:'默认参数',//接受默认数据
  },
  money:{
   type:Number,
   default:0
}})

子组件获取父组件传递数据:方式2 

let props = defineProps(["info",'money']);

案例

父组件

<template>
  <div class="box">
    <h1>props:我是父组件曹操</h1>
    <hr />
    <Child info="我是曹操" :money="money"></Child>
  </div>
</template>

<script setup lang="ts">
//props:可以实现父子组件通信,props数据还是只读的!!!
import Child from "./Child.vue";
import { ref } from "vue";
let money = ref(10000);
</script>

<style scoped>
.box {
  width: 100vw;
  height: 400px;
  background: yellowgreen;
}
</style>

props可以实现父子组件通信,在vue3中我们可以通过defineProps获取父组件传递的数据。且在组件内部不需要引入defineProps方法可以直接使用!

子组件

<template>
  <div class="son">
       <h1>我是子组件:曹植</h1>
       <p>{{props.info}}</p>
       <p>{{props.money}}</p>
      <!--props可以省略前面的名字--->
       <p>{{info}}</p>
       <p>{{money}}</p>
       <button @click="updateProps">修改props数据</button>
  </div>
</template>

<script setup lang="ts">
//需要使用到defineProps方法去接受父组件传递过来的数据
//defineProps是Vue3提供方法,不需要引入直接使用
let props = defineProps(['info','money']); //数组|对象写法都可以
//按钮点击的回调
const updateProps = ()=>{
  // props.money+=10;  props:只读的
  console.log(props.info)
}
</script>

<style scoped>
.son{
  width: 400px;
  height: 200px;
  background: hotpink;
}
</style>

自定义事件

在vue框架中事件分为两种:一种是原生的DOM事件,另外一种自定义事件。

  • 原生DOM事件可以让用户与网页进行交互,比如click、dbclick、change、mouseenter、mouseleave....
  • 自定义事件可以实现子组件给父组件传递数据

原生DOM事件

代码如下:

<pre @click="handler"> 我是祖国的老花骨朵 </pre>

当前代码级给pre标签绑定原生DOM事件点击事件,默认会给事件回调注入event事件对象。当然点击事件想注入多个参数可以按照下图操作。但是切记注入的事件对象务必叫做$event.

  <div @click="handler1(1,2,3,$event)">我要传递多个参数</div>

在vue3框架click、dbclick、change(这类原生DOM事件),不管是在标签、自定义标签上(组件标签)都是原生DOM事件。

自定义事件

自定义事件可以实现子组件给父组件传递数据.在项目中是比较常用的。

比如在父组件内部给子组件(Event2)绑定一个自定义事件

<Event2  @xxx="handler3"></Event2>

在Event2子组件内部触发这个自定义事件

<template>
  <div>
    <h1>我是子组件2</h1>
    <button @click="handler">点击我触发xxx自定义事件</button>
  </div>
</template>

<script setup lang="ts">
let $emit = defineEmits(["xxx"]);
const handler = () => {
  $emit("xxx", "法拉利", "茅台");
};
</script>
<style scoped>
</style>

我们会发现在script标签内部,使用了defineEmits方法,此方法是vue3提供的方法,不需要引入直接使用。defineEmits方法执行,传递一个数组,数组元素即为将来组件需要触发的自定义事件类型,此方执行会返回一个$emit方法用于触发自定义事件。

当点击按钮的时候,事件回调内部调用$emit方法去触发自定义事件,第一个参数为触发事件类型,第二个、三个、N个参数即为传递给父组件的数据。

需要注意的是:代码如下

<Event2  @xxx="handler3" @click="handler"></Event2>

正常说组件标签书写@click应该为原生DOM事件,但是如果子组件内部通过defineEmits定义就变为自定义事件了

let $emit = defineEmits(["xxx",'click']);

案例

父组件

原生DOM事件可以让用户与网页进行交互,比如click、dbclick、change、mouseenter、mouseleave....

<template>
  <div>
    <h1>事件</h1>
    <!-- 原生DOM事件 -->
    <pre @click="handler">
      大江东去浪淘尽,千古分流人物
    </pre>
    <button @click="handler1(1,2,3,$event)">点击我传递多个参数</button>
    <hr>
    <!--
        vue2框架当中:这种写法自定义事件,可以通过.native修饰符变为原生DOM事件
        vue3框架下面写法其实即为原生DOM事件

        vue3:原生的DOM事件不管是放在标签身上、组件标签身上都是原生DOM事件
      -->
    <Event1 @click="handler2"></Event1>
    <hr>
    <!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
    <Event2 @xxx="handler3" @click="handler4"></Event2>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Event1 from './Event1.vue';
//引入子组件
import Event2 from './Event2.vue';
//事件回调--1
const handler = (event)=>{
    //event即为事件对象
    console.log(event);
}
//事件回调--2
const handler1 = (a,b,c,$event)=>{
   console.log(a,b,c,$event)
}
//事件回调---3
const handler2 = ()=>{
    console.log(123);
}
//事件回调---4
const handler3 = (param1,param2)=>{
    console.log(param1,param2);
}
//事件回调--5
const handler4 = (param1,param2)=>{
     console.log(param1,param2);
}
</script>

<style scoped>
</style>

子组件一

  •         vue3:原生的DOM事件不管是放在标签身上、组件标签身上都是原生DOM事件
  •         vue2框架当中:这种写法自定义事件,可以通过.native修饰符变为原生DOM事件
  •         绑定在子组件的根节点上
<template>
  <div class="son">
      <p>我是子组件1</p>
      <button>点击我也执行</button>
  </div>
</template>

<script setup lang="ts">

</script>

<style scoped>
.son{
  width: 400px;
  height: 200px;
  background: skyblue;
}
</style>

子组件二

  • //利用defineEmits方法返回函数触发自定义事件
  •  //第一个参数:事件类型 第二个|三个|N参数即为注入数据
  • //defineEmits方法不需要引入直接使用
  • 正常说组件标签书写@click应该为原生DOM事件,但是如果子组件内部通过defineEmits定义就变为自定义事件了
<template>
  <div class="child">
    <p>我是子组件2</p>
    <button @click="handler">点击我触发自定义事件xxx</button>
    <button @click="$emit('click','AK47','J20')">点击我触发自定义事件click</button>
  </div>
</template>

<script setup lang="ts">
//利用defineEmits方法返回函数触发自定义事件
//defineEmits方法不需要引入直接使用
let $emit = defineEmits(['xxx','click']);
//按钮点击回调
const handler = () => {
  //第一个参数:事件类型 第二个|三个|N参数即为注入数据
    $emit('xxx','东风导弹','航母');
};
</script>

<style scoped>
.child {
  width: 400px;
  height: 200px;
  background: pink;
}
</style>

全局事件总线

全局事件总线可以实现任意组件通信,在vue2中可以根据VM与VC关系推出全局事件总线。

但是在vue3中没有Vue构造函数,也就没有Vue.prototype.以及组合式API写法没有this,

那么在Vue3想实现全局事件的总线功能就有点不现实啦,如果想在Vue3中使用全局事件总线功能

可以使用插件mitt实现。

mitt:官网地址:mitt - npm

 引入mitt插件:mitt一个方法,方法执行会返回bus对象

案例 ------------------

导出 mitt

引入mitt插件:mitt一个方法,方法执行会返回bus对象

//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const $bus = mitt();
export default $bus;

父组件

<template>
  <div class="box">
    <h1>全局事件总线$bus</h1>
    <hr />
    <div class="container">
      <Child1></Child1>
      <Child2></Child2>
    </div>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
</script>

<style scoped>
.box {
  width: 100vw;
  height: 400px;
  background: yellowgreen;
}
.container{
  display: flex;
  justify-content: space-between;
}
</style>

子组件一:订阅消息 

//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据

 //第一个参数:即为事件类型  第二个参数:即为事件回调

<template>
  <div class="child1">
    <h3>我是子组件1:曹植</h3>
  </div>
</template>

<script setup lang="ts">
import $bus from "../../bus";
//组合式API函数
import { onMounted } from "vue";
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
onMounted(() => {
  //第一个参数:即为事件类型  第二个参数:即为事件回调
  $bus.on("car", (car) => {
    console.log(car);
  });
});
</script>

<style scoped>
.child1 {
  width: 300px;
  height: 300px;
  background: hotpink;
}
</style>

子组件二 发布消息

<template>
  <div class="child2">
     <h2>我是子组件2:曹丕</h2>
     <button @click="handler">点击我给兄弟送一台法拉利</button>
  </div>
</template>

<script setup lang="ts">
//引入$bus对象
import $bus from '../../bus';
//点击按钮回调
const handler = ()=>{
  $bus.emit('car',{car:"法拉利"});
}
</script>

<style scoped>
.child2{
  width: 300px;
  height: 300px;
  background: skyblue;
}
</style>

v-model

v-model指令可是收集表单数据(数据双向绑定),除此之外它也可以实现父子组件数据同步。

而v-model实指利用props[modelValue]与自定义事件[update:modelValue]实现的。

下方代码:相当于给组件Child传递一个props(modelValue)与绑定一个自定义事件update:modelValue

实现父子组件数据同步

<Child v-model="msg"></Child>

在vue3中一个组件可以通过使用多个v-model,让父子组件多个数据同步,下方代码相当于给组件Child传递两个props分别是pageNo与pageSize,以及绑定两个自定义事件update:pageNo与update:pageSize实现父子数据同步

<Child v-model:pageNo="msg" v-model:pageSize="msg1"></Child>

案例 ----------------

父组件

v-model指令可是收集表单数据(数据双向绑定),除此之外它也可以实现父子组件数据同步。

<template>
  <div>
    <h1>v-model:钱数{{ money }}</h1>
    <h1>pageNo:{{ pageNo }}</h1>
    <h1>pageSize:{{ pageSize }}</h1>
    <input type="text" v-model="info" />
    <hr />
    <!-- props:父亲给儿子数据 -->
    <Child :modelValue="money" @update:modelValue="handler"></Child>
    <!-- 
       v-model组件身上使用
       第一:相当有给子组件传递props[modelValue] = 10000
       第二:相当于给子组件绑定自定义事件update:modelValue
     -->
    <Child v-model="money"></Child>
    <hr />
    <Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
  </div>
</template>

<script setup lang="ts">
//v-model指令:收集表单数据,数据双向绑定
//v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
//父亲给子组件数据 props
//子组件给父组件数据 自定义事件
//引入子组件
import Child from "./Child.vue";
import Child1 from "./Child1.vue";
import { ref } from "vue";
let info = ref("");
//父组件的数据钱数
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num;
};

//父亲的数据
let pageNo = ref(1);
let pageSize = ref(3);
</script>

<style scoped>
</style>

子组件一

  • 父传子:子组件传递props给父组件
  • 子传父:子组件绑定自定义事件触发父子件事件
<template>
  <div class="child">
    <h3>钱数:{{ modelValue }}</h3>
    <button @click="handler">父子组件数据同步</button>
  </div>
</template>

<script setup lang="ts">
//接受props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
   //触发自定义事件
   $emit('update:modelValue',props.modelValue+1000);
}
</script>

<style scoped>
.child {
  width: 600px;
  height: 300px;
  background: skyblue;
}
</style>

子组件二

 v-model组件身上使用

  •        第一:相当有给子组件传递props[modelValue] = 10000
  •        第二:相当于给子组件绑定自定义事件update:modelValue
  •        可以绑定多个
<template>
  <div class="child2">
    <h1>同时绑定多个v-model</h1>
    <button @click="handler">pageNo{{ pageNo }}</button>
    <button @click="$emit('update:pageSize', pageSize + 4)">
      pageSize{{ pageSize }}
    </button>
  </div>
</template>

<script setup lang="ts">
let props = defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits(["update:pageNo", "update:pageSize"]);
//第一个按钮的事件回调
const handler = () => {
  $emit("update:pageNo", props.pageNo + 3);
};
</script>

<style scoped>
.child2 {
  width: 300px;
  height: 300px;
  background: hotpink;
}
</style>

useAttrs

在Vue3中可以利用useAttrs方法获取组件的属性与事件(包含:原生DOM事件或者自定义事件),次函数功能类似于Vue2框架中$attrs属性与$listeners方法。

比如:在父组件内部使用一个子组件my-button

<my-button type="success" size="small" title='标题' @click="handler"></my-button>

子组件内部可以通过useAttrs方法获取组件属性与事件.因此你也发现了,它类似于props,可以接受父组件传递过来的属性与属性值。需要注意如果defineProps接受了某一个属性,useAttrs方法返回的对象身上就没有相应属性与属性值。

<script setup lang="ts">
import {useAttrs} from 'vue';
let $attrs = useAttrs();
</script>

父组件

<template>
  <div>
    <h1>useAttrs</h1>
    <el-button type="primary" size="small" :icon="Edit"></el-button>
    <!-- 自定义组件 -->
    <HintButton type="primary" size="small" :icon="Edit" title="编辑按钮" @click="handler" @xxx="handler"></HintButton>
  </div>
</template>

<script setup lang="ts">
//vue3框架提供一个方法useAttrs方法,它可以获取组件身上的属性与事件!!!
//图标组件
import {
  Check,
  Delete,
  Edit,
  Message,
  Search,
  Star,
} from "@element-plus/icons-vue";
import HintButton from "./HintButton.vue";
//按钮点击的回调
const handler = ()=>{
  alert(12306);
}
</script>

<style scoped>
</style>

子组件

//props与useAttrs方法都可以获取父组件传递过来的属性与属性值

//但是props接受了useAttrs方法就获取不到了

<template>
  <div :title="title">
     <el-button :="$attrs"></el-button>   
  </div>
</template>

<script setup lang="ts">
//引入useAttrs方法:获取组件标签身上属性与事件
import {useAttrs} from 'vue';
//此方法执行会返回一个对象
let $attrs = useAttrs();

//万一用props接受title
let props =defineProps(['title']);
//props与useAttrs方法都可以获取父组件传递过来的属性与属性值
//但是props接受了useAttrs方法就获取不到了
console.log($attrs);
</script>

<style scoped>
</style>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue3组件通信方式一 的相关文章

随机推荐

  • HTML中的数据存储

    一 什么是Web Storage 在HTML5中 除了新增canvas元素之外 还新增的非常重要的功能是可以在客户端本地保存数据的WebStorage功能 Web应用的发展 使得客户端存储功能使用得越来越多 而实现客户端存储的方式则是多种多
  • 为什么vue3要选用proxy,好处是什么?

    提问 Object defineProperty 和proxy的区别 为什么vue3要选用proxy 好处是什么 proxy Proxy 对象用于创建一个对象的代理 从而实现基本操作的拦截和自定义 如属性查找 赋值 枚举 函数调用等 Pro
  • SQOOP从mysql导入数据到hive问题

    需要将mysql一张表的数据导入到hive表当中 初始的执行命令如下 sqoop import connect jdbc mysql 10 1 x x 3306 dbname characterEncoding utf 8 username
  • 软件测试之系统测试必备知识

    一 软件系统测试定义 软件系统测试是对整个系统的测试 将硬件 软件 操作人员看作一个整体 检验它是否有不符合系统说明书的地方 这种测试可以发现系统分析和设计中的错误 二 软件系统测试目的 通过与系统的需求定义作比较 发现软件与系统定义不符合
  • Markdown语法简介

    Markdown是一种方便记忆 书写的纯文本标记语言 用户可以使用这些标记符号以最小的输入代价生成极富表现力的文档 它目标是实现易读易写 Markdown的语法全由一些符号所组成 Markdown语法的目标是成为一种适用于网络的书写语言 M
  • java 重新加载spring_SpringBoot的reload加载器的方法

    背景 出现了相同类castException 分析 首先确定出现相同类的castException比如是由于classloader不同造成的 一个class是否相同取决于两个因素 classloader相同 class文件相同 即不同cla
  • Failed to execute goal org.apache .maven.plugins.maven-resounces-plugin:3.2.0:resounces

    1 在部署微服务系统的服务中心和服务提供者时 在打包的过程中 出现过如下的错误 Failed to execute goal org apache maven plugins maven resounces plugin 3 2 0 res
  • 谁说 AI 编程工具缺乏记忆和联想能力?简单琐碎的需求完全可以交给它

    Amazon CodeWhisperer 是一款 AI 编码配套应用程序 可在 IDE 中生成整行代码和完整的函数代码建议 以帮助您更快地完成更多工作 在本系列文章中 我们将为您详细介绍 Amazon CodeWhisperer 的相关信息
  • 如果虚函数在基类与子类名字相同,而参数类型不同不会进行迟后联编

    class Base public virtual void Show int x cout lt lt In Base class int x lt lt x lt lt endl class Derived public Base pu
  • 2020-08-27

    java 1 编译java程序的命令是javac 该命令的文件是javac exe 2 jsp表达式的写法 3 3 Math round 11 5 为 11 四舍五入是向数值大的方向入 4 float与int做除法运算时 会将int转化为f
  • 基础项目(2)二选一数据选择器的设计

    写在前面的话 数据选择器在数字电路设计中的应用尤为广泛 同时 作为基础的电路功能单元 也比较适合作为初学者的入门实验 现在梦翼师兄陪大家一起来设计一个最基础的数据选择器 项目需求 设计一个二选一数据选择器 然后用一路控制信号选择输出数据选通
  • 区块链中的全节点与轻量级节点

    在加密货币中 凡是连接到该网络的任何计算机 都被称为节点 在区块链中 存在一种冗余备份的现象 就是说 如果所有节点都需要保存全网的所有交易及其他数据信息 则不可避免的会出现一些弊端 比如 用户想创建一个自己的区块链节点进行项目开发 而不需要
  • 华为OD机试 - 返回矩阵中非1的元素个数(Java)

    题目描述 存在一个m n的二维数组 其成员取值范围为0 1 2 其中值为1的元素具备同化特性 每经过1S 将上下左右值为0的元素同化为1 而值为2的元素 免疫同化 将数组所有成员随机初始化为0或2 再将矩阵的 0 0 元素修改成1 在经过足
  • 微信小程序:setdata--数据如何输出到前台

    简介 这一部分我来为大家讲解一下啊 小程序前台wxml页面如何调用后台的数据 其中涉及到的一个方法 setdata 演示 前 wxml
  • Python二级--三国演义分词

    三国演义分词 1 题目一 概述 三国演义 是中国古典四大名著之一 曹操是其中主要人物 考生文件夹下文件data txt给出 三 国演义 简介 问题1 请编写程序 用Python语言中文分词第三方库jieba对文件data txt进行分词 并
  • Flutter SingleChildScrollView要点

    知识要点 SingleChildScrollView类似Android中的ScrollView 只接收一个子组件 SingleChildScrollView this scrollDirection Axis vertical 滚动方向 默
  • Springboot中如何打印sql信息和sql参数信息呢?

    转自 Springboot中如何打印sql信息和sql参数信息呢 下文笔者讲述SpringBoot中设置配置文件 使其可打印出sql信息及参数信息的方法分享 实现思路 springboot打印sql信息及参数 我们可采用修改applicat
  • python:openpyxl基础操作(一):创建.xlsx文件

    目录 前言 安装openpyxl 创建 xlsx文件 添加单元格内容 单个添加 多个添加 增删单元格 遍历表格中的值 合并拆分单元格 前言 本文仅供个人学习记录 复习所用 探索过程中难免出现差错和纰漏 如文中有错误 以及可以改进的地方 还请
  • python中的utils模块_python常用方法utils

    always 目录里主要封装了一些自己常用的方法 1 doc2txt 本函数主要目的是方便在写爬虫的时候遇到word附件 下载后直接提取出文本文件 注意 需要安装antiword mac下 brew install antiword 2 f
  • vue3组件通信方式一

    目录 props 父组件给子组件传递数据 子组件获取父组件传递数据 方式1 子组件获取父组件传递数据 方式2 案例 自定义事件 原生DOM事件 自定义事件 案例 全局事件总线 v model useAttrs 不管是vue2还是vue3 组