Vue3组件间的通信方式

这篇具有很好参考价值的文章主要介绍了Vue3组件间的通信方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

 1.props父向子组件通信

2.自定义事件 子向父组件通信

3.全局事件总线

4.v-model组件通信(父子组件数据同步)

绑定单个数据同步 

绑定多个数据同步 

5.useAttrs组件通信

 6.ref与$parent

ref获取子组件实例对象

 $parent获取父组件实例对象

 7.provide-inject 可以实现隔辈传输

8.Pinia

选择式API:

组合式API:


我们用Vue3开发项目时,常常需要面对的一个问题就是组件之间的通信,如何将数据发给对应的组件,这是不可避免的一个问题,该篇讲述了Vue3的8大主要通信方式。(还有其他的可以补充)

 1.props父向子组件通信

父组件:

props用于父组件向子组件传递数据,子组件用defineProps接收父组件传递来的参数

在父组件中我们可以在使用子组件时,对其传递props数据

<Child info="父组件" v-bind:money="10000"></Child>

其中没有使用v-bind的数据为固定数据,如果使用v-bind即是动态的数据

子组件:

在子组件中接收数据

//defineProps是Vue3提供方法,不需要引入直接使用
let props = defineProps(['info', 'money'])

这种方式是简单写法,还有一种对象写法,用法更加的多,可以规定数据类型和默认值/

let props = defineProps({
  info: {
    type: String,
    required: true, //是否规定必须得有
    default: 'info默认值'
  },
  money: {
    type: Number,
    required: true, //是否规定必须得有
    default: 9999  //默认数据,当父组件没有传递数据时,读取该数据
  }

在子组件中使用也是很简单(这二种方式都可以)

    <p>{{props.info}}</p>
    <p>{{props.money}}</p>
    <!--props可以省略前面的名字--->
    <p>{{info}}</p>
    <p>{{money}}</p>

注意点:props的数据为只读数据,不可以进行修改

2.自定义事件 子向父组件通信

父组件

父组件中接收自定义事件

<!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
<Event2 @xxx="handler3"></Event2>
//事件回调---4
const handler3 = (val1, val2) => {
  console.log(val1, val2)
}

子组件

主要是子组件利用defineEmits方法返回函数触发自定义事件

//利用defineEmits方法返回函数触发自定义事件
//defineEmits方法不需要引入直接使用
let $emit = defineEmits(['xxx'])

绑定事件传递参数

<button @click="handler">点击我触发自定义事件xxx</button>

//按钮点击回调
const handler = () => {
  //第一个参数:事件类型 第二个|三个|N参数即为注入数据
  $emit('xxx', 'data1', 'data2')
}

点击按钮时会传递数据到父组件,父组件会接收到对应的参数

3.全局事件总线

由于在Vue3中,其vue构造函数被移除,导致其没有了VM,无法做到$bus全局事件总线,要想实现全局事件总线可以使用mitt插件来实现

可以在项目中安装mitt

npm install --save mitt

在需要传递数据的组件中 $bus.emit方法是传递数据

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

 在接收数据的组件中,$bus.on即是接收数据的方法

import mitt from 'mitt'
const $bus = mitt()

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

4.v-model组件通信(父子组件数据同步)

大家对v-model的印象可能只是觉得它可以用来实现表单数据的双向绑定,但其实它还可以用来实现父子组件数据同步

绑定单个数据同步 

如果我们不使用v-model,要想让父子组件的数据同步,许哟同时用到props和自定义事件才可以实现,像下面这样:

父组件:

//props:父亲给儿子数据
<Child :modelValue="money" @update:modelValue="handler"></Child>

<script setup lang="ts">
import Child from './Child.vue'
import { ref } from 'vue'
let money = ref(10000)
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num
}
</script>

子组件:

<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>

可以看到我们需要同时用到了props和自定义事件可以实现父子组件的数据同步

使用v-model是实现:

只需要修改子组件的标签就行

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

       v-model在组件身上使用

       1:相当有给子组件传递props[modelValue] = 10000

       2:相当于给子组件绑定自定义事件update:modelValue

绑定多个数据同步 

父组件:

<Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
//父亲的数据
let pageNo = ref(1)
let pageSize = ref(3)

子组件接收:

<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>

其主要实现原理还是利用了props和自定义事件的组合使用,v-model只是帮我们同步了数据和方法

5.useAttrs组件通信

父组件:将message属性传递给子组件

<template>
  <div>
    <input v-model="message">
    <HidtButton :message="message" />
  </div>
</template>

<script setup lang="ts">
import HidtButton from './HintButton.vue'
import { ref } from 'vue'

const message = ref('')
</script>

子组件:用useAttrs接收并展示数据

<template>
  <div>
    <p>{{ $attrs.message }}</p>
  </div>
</template>

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

useAttrs可以接收到父组件的属性Vue3组件间的通信方式,vue,前端,vue.js,前端,typescript

这样就实现了子组件接收父组件的数据

Vue3组件间的通信方式,vue,前端,vue.js,前端,typescript

useAttrs的功能于props的功能很类似,都是父组件传递数据给子组件,如果使用了props和useAttrs同时接收数据,props的优先级比useAttrs高

 6.ref与$parent

ref获取子组件实例对象

ref:可以获取真实的DOM节点,可以获取到子组件实例VC,在父组件中拿到子组件的实例,那么就可以操作子组件的属性及方法了,默认情况下是不能拿到的,子组件需要对外暴露才行

父组件:

<template>
  <div class="box">
    <h1>我是父组件:{{money}}</h1>
    <button @click="handler">找我的儿子借10元</button>
    <Son ref="son"></Son>
  </div>
</template>

<script setup lang="ts">
//ref:可以获取真实的DOM节点,可以获取到子组件实例VC
//$parent:可以在子组件内部获取到父组件的实例
//引入子组件
import Son from './Son.vue'
import { ref } from 'vue'
//父组件钱数
let money = ref(100000000)
//获取子组件的实例
let son = ref()
//父组件内部按钮点击回调
const handler = () => {
  console.log(son.value)//打印子组件的实例对象
  money.value += 10
  //儿子钱数减去10
  son.value.money -= 10
  son.value.fly()
}
})

 子组件:

<template>
  <div class="son">
    <h3>我是子组件:{{money}}</h3>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
//儿子钱数
let money = ref(666)
const fly = () => {
  console.log('我可以飞')
}
//组件内部数据对外关闭的,别人不能访问
//如果想让外部访问需要通过defineExpose方法对外暴露
defineExpose({
  money,
  fly
})
</script>

子组件的实例对象:Vue3组件间的通信方式,vue,前端,vue.js,前端,typescript 

 $parent获取父组件实例对象

$parent:可以在子组件内部获取到父组件的实例

父组件只要放子组件即可:

<Dau></Dau>
<script setup lang="ts">
//$parent:可以在子组件内部获取到父组件的实例
//引入子组件
import Dau from './Daughter.vue'
import { ref } from 'vue'
//父组件钱数
let money = ref(100000000)
//对外暴露
defineExpose({
  money
)}
</script>

在子组件中用$parent获取到父组件的实例对象,当然我们的父组件也需要对外暴露才能让子组件拿到实例对象

<template>
  <div class="dau">
    <h1>我是子组件{{money}}</h1>
    <button @click="handler($parent)">点击我父组件给我10000元</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
//子组件钱数
let money = ref(999999)
//子组件按钮点击回调
const handler = ($parent: any) => {
  console.log($parent)
  money.value += 10000
  $parent.money -= 10000
}
</script>

利用点击事件注入$parent拿到父亲的实例对象Vue3组件间的通信方式,vue,前端,vue.js,前端,typescript

 7.provide-inject 可以实现隔辈传输

父组件:用provide传输对应的数据,并提供一个key,后续的子组件在拿数据也是根据此key

<template>
  <div class="box">
    <h1>Provide与Inject{{car}}</h1>
    <hr />
    <Child></Child>
  </div>
</template>

<script setup lang="ts">
import Child from "./Child.vue";
//vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据
import { ref, provide } from "vue";
let car = ref("法拉利");
//祖先组件给后代组件提供数据
//两个参数:第一个参数就是提供的数据key
//第二个参数:祖先组件提供数据
provide("TOKEN", car);
</script>

子组件:使用inject和对应的key获取到对应的数据

<template>
  <div class="child">
    <h1>我是子组件1{{ car }}</h1>
    <Child></Child>
  </div>
</template>

<script setup lang="ts">
import Child from './GrandChild.vue'
import { inject } from 'vue'
//注入祖先组件提供数据
//需要参数:即为祖先提供数据的key
let car = inject('TOKEN')
</script>

孙组件:数据可以进行修改,而且所有的组件数据都是同步的

<template>
  <div class="child1">
    <h1>孙子组件</h1>
    <p>{{car}}</p>
    <button @click="updateCar">更新数据</button>
  </div>
</template>

<script setup lang="ts">
import {inject} from 'vue';
//注入祖先组件提供数据
//需要参数:即为祖先提供数据的key
let car = inject('TOKEN');
const updateCar = ()=>{
   car.value  = '自行车';
}
</script>

8.Pinia

相比于 Vuex,Pinia 提供了更简洁直接的 API,并提供了组合式风格的 API,最重要的是,在使用 TypeScript 时它提供了更完善的类型推导。

这也是vue官方更加推荐的状态集中管理工具的原因

Vue3组件间的通信方式,vue,前端,vue.js,前端,typescript

 在使用pinia时需要安装其依赖

npm i pinia

 pinia可以支持vue2和vue3,所以有二种写法,组合式和选择式

1.新建仓库文件store创建index.ts大仓库

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

2.在mian.js中引用

//引入仓库
import store from './store'
//使用
app.use(store)

选择式API:

state存放数据

actions实现方法(可以之间修改数据)

getters计算属性

//定义info小仓库
import { defineStore } from "pinia";
//第一个仓库:小仓库名字  第二个参数:小仓库配置对象
//defineStore方法执行会返回一个函数,函数作用就是让组件可以获取到仓库数据
let useInfoStore = defineStore("info", {
    //存储数据:state
    state: () => {
        return {
            count: 99,
            arr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        }
    },
    actions: {
        //注意:函数没有context上下文对象
        //没有commit、没有mutations去修改数据
        updateNum(a: number, b: number) {
            this.count += a;
        }
    },
    getters: {
       
    }
});
//对外暴露方法
export default useInfoStore;

在组件中使用pinia数据

<template>
  <div class="child">
    <h1>{{ infoStore.count }}---{{infoStore.total}}</h1>
    <button @click="updateCount">点击我修改仓库数据</button>
  </div>
</template>

<script setup lang="ts">
import useInfoStore from "../../store/modules/info";
//获取小仓库对象
let infoStore = useInfoStore();
console.log(infoStore);
//修改数据方法
const updateCount = () => {
  //仓库调用自身的方法去修改仓库的数据
  infoStore.updateNum(66,77);
};
</script>

组合式API:

//定义组合式API仓库
import { defineStore } from "pinia";
import { ref, computed } from 'vue';
//创建小仓库
let useTodoStore = defineStore('todo', () => {
    let arr = ref([1,2,3,4,5]);

    const total = computed(() => {
        return arr.value.reduce((prev, next) => {
            return prev + next;
        }, 0)
    })
    function updateTodo() {
        arr.value.push(0)
    }
    //务必要返回一个对象:属性与方法可以提供给组件使用
    return {
        arr,
        total,
        updateTodo
    }
});

export default useTodoStore;

在组件中使用:文章来源地址https://www.toymoban.com/news/detail-581101.html

<template>
  <div class="child1">
    <p @click="updateTodo">{{ todoStore.arr }}</p>
  </div>
</template>

<script setup lang="ts">
//引入组合式API函数仓库
import useTodoStore from "../../store/modules/todo";
let todoStore = useTodoStore();

//点击p段落去修改仓库的数据
const updateTodo = () => {
  todoStore.updateTodo();
};
</script>

到了这里,关于Vue3组件间的通信方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3.2+TS的组件间的v-model传值

    组件之间的v-model,为什么可以v-model,大家可以去看看v-model的原理,然后就会发现这个方法一目了然。 父组件 子组件 假如子组件需要按照某个方法变化,那么可以自己定义,比如需要自增加50

    2024年02月13日
    浏览(47)
  • 前端vue3+typescript架构

    1、vue creat 项目名称 选择自定义  选择需要的依赖  选择vue3  一路enter,选择eslist+prettier  继续enter,等待安装 按步骤操作,项目启动成功  2、vscode安装5款插件  2、代码保存自动格式化,保证每个开发人员代码一致,根目录新建三个文件.editorconfig和.prettierrc和.prettierignore

    2024年02月11日
    浏览(40)
  • vue3项目+TypeScript前端项目—— vue3搭建项目+eslint+husky

    今天来带大家从0开始搭建一个vue3版本的后台管理系统。一个项目要有统一的规范,需要使用eslint+stylelint+prettier来对我们的代码质量做检测和修复,需要使用husky来做commit拦截,需要使用commitlint来统一提交规范,需要使用preinstall来统一包管理工具。 下面我们就用这一套规范

    2024年02月22日
    浏览(82)
  • 《Vue3+Typescript》一个简单的日历组件实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~ 主页: oliver尹的主页 格言: 跌倒了爬起来就好~ 目录 一、前言 二、效果图 三、核心思路 四、代码实现 4.1 本月日期

    2024年02月14日
    浏览(42)
  • Vue3,Typescript中引用组件路径无法找到模块报错

    是这么个事,我在vue3新创建的项目里,写了个组件叫headerIndex.vue,放到app.vue中import就会报错 路径肯定没写错,找到了解决方法,但是也没想明白为什么 解决方法如下 在vite-env.d.ts文件中加入 就好了,大概意思就是在文件中把组件声明一下,but why

    2024年02月09日
    浏览(42)
  • VUE3 组件通信

    用途:可以实现父子组件、子父组件、甚至兄弟组件通信 父组件 子组件 用途:可以实现子父组件通信 父组件 子组件 用途:可以实现任意组件通信 安装  配置 新建bus.js文件 使用 父组件 子组件 父组件 子组件 父组件 子组件 父组件 子组件 父组件 儿子组件1 儿子组件2 安装

    2024年03月19日
    浏览(46)
  • vue3.0组件通信

    没有加TS限制类型的时候 注意: defineProps()会返回一个对象,这个对象可以直接.出数据 加TS写法 规则: 非函数类型 基本数据类型 - 展示 引用数据类型 - 展示,但是可以修改属性,不推荐(违反单向数据流 - 不是绝对禁止使用的,偷懒可以用) 函数类型 - 子组件调用父组件传过来的函数

    2024年02月12日
    浏览(44)
  • vue3组件通信详解

    vue3组件通信方式有以下几种:porps,$emit, bus,v-model, useAttrs ,$ref/$parent,provide/inject,pinia,slot。下面将逐一讲解。    目录 1.porps:实现父子组件通信,子组件接收的数据还是只读  2.$emit 3.全局事件总线 $bus,使用mitt 4.v-model传值 5. $attrs/useAttrs:获取组件标签身上属性与

    2024年02月07日
    浏览(38)
  • 用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能。

    Vue3 的父子组件传值、绑定表单数据、UI库的二次封装、防抖等,想来大家都很熟悉了,本篇介绍一种使用 Typescript 的方式进行统一的封装的方法。 Vue3对于表单的绑定提供了一种简单的方式: v-model 。对于使用者来说非常方便, v- model=\\\"name\\\" 就可以了。 但是当我们要自己做一

    2024年02月06日
    浏览(43)
  • vue3组件通信学习笔记

    父组件 子组件 父组件 子组件 子组件1 子组件2 父组件 子组件 父组件 子组件 父组件 子组件 父组件 子组件 父组件 子组件 孙子组件 1、选择式写法 1、info.js 2、在组件1中使用 3、在组件2中使用 2、组合式API写法 1、在modules文件夹下新建todo.js 2、在组件1中使用 3、在组件2中使

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包