Vue3组件通信相关内容整理

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

一、props方式:父<->子通信

适用于:  父向子传递参数、方法, 子触发父传递的方法

props方式组件通信和vue2中的props传参类似,只是使用方式和接收方式有一些区别。

注意点: 通过props方式传递的参数为只读属性,不可修改

父组件

<template>
  <div class="">
    <h3>父组件</h3>
    <Children :car="car" :sendToyFn="getChildToyFn"/>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import Children from "./children.vue";
let car = ref('小绵羊')
function getChildToyFn(val:string){
  console.log('父拿到的:',val);
}
</script>

子组件 

<template>
  <div class="">
    <h3>子组件</h3>
    <p>玩具:{{ toy }}</p>
    <p>父亲的车:{{ car }}</p>
    <button @click="sendToyFn(toy)">把玩具给父亲</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
let toy = ref('哑铃')
// 声明接收  如果要在script标签中使用接收的参数,就必须先接收defineProps的返回值
let props = defineProps(['car','sendToyFn'])
// console.log(car); // 不能拿到接收的car
console.log(props.car)

</script>
<style lang="scss" scoped>

</style>

二、自定义事件:子->父通信

// 父组件
<Children @set-toy-fn="getToyFn"/>
// 子组件
// 通过 defineEmits 接收父组件传递来的方法
const emit = defineEmits(['set-toy-fn'])
// 调用方法 emit('方法名',参数1,参数2...)
emit('set-toy-fn','玩具')

三、mitt方式:任意组件通信

1、首先要安装  npm i mitt

2、在src/utils/下新建文件 emitter.ts(可自定义文件位置以及命名)

3、在emitter.ts文件中引入、创建、导出mitt

import mitt from "mitt";
// 调用mitt得到emitter ,emitter能绑定事件、触发事件
const emiiter = mitt()
// 四个api:  all-操作所有事件 emit-触发事件 off-解绑事件 on-绑定某一个事件
export default emiiter

4、在组件中使用

组件A :绑定事件-接收数据

import { ref } from 'vue'
import emitter from "@/utils/emitter.ts";
let num = ref(0)
// 绑定事件
emitter.on('getData',(data)=>{
  num.value ++ 
  console.log('拿到了数据:',data);
  if(num.value==3){
    emitter.off('getData');// 解除绑定
  }
})

 组件B:触发事件-传递数据

import { ref,reactive } from 'vue'
import emitter from "@/utils/emitter.ts";

let info = reactive({
  userName:'张三',
  userId:'007'
})
let toy = ref('小猪佩奇')
function toData() {
  // 触发事件并传递参数
  emitter.emit('getData',{info ,toy})
  
}

四、v-model传参:父<->子通信

这种方式可以参考Vue3-在HTML标签、组件标签上使用v-model,这里就不再详述

五、$attrs:父->子->孙

$attrs:父组件通过props向子组件传参时,子组件未声明接收的值。通过$attrs接收到的参数是只读

父组件 

<template>
  <div class="">
    <p>父组件</p>
    <p>b:{{ b }}</p>
    <Children v-bind="{a,b,c,d,addA}"/>
    <!-- 这种写法相当于 -->
    <!-- <Children :a="a" :b="b" :c="c" :d="d" :addA="addA"/> -->
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import Children from "./children.vue";
let a = ref(1)
let b = ref(2)
let c = ref(3)
let d = ref(4)
function addA(num:number=1){
  a.value += num
}
</script>

子组件 

// 子组件  在子组件中不对父组件传递的参数做任何操作
// 传递的方法值不在页面中显示 但是可以直接通过 $attrs.方法名 调用
<template>
  <div class="">
    <p>子组件</p>
    {{ $attrs }} // { "a": 1, "b": 2, "c": 3, "d": 4 } 
    {{ $attrs.addA }} // function addA(num = 1) { a.value += num; }
    <hr/>
    <GrandChild v-bind="$attrs"/>
  </div>
</template>

<script setup lang="ts">
import GrandChild from "./grandChild.vue";

</script>
<style lang="scss" scoped>

</style>

孙组件

<template>
  <div class="">
    <p>孙组件</p>
    <p>$attrs的值:{{$attrs}}</p> // { "b": 2, "c": 3, "d": 4 }
    <button @click="(<Function>$attrs.addA)(2)">触发父组件方法</button> // 此处为ts的类型断言,ts不能确定$attrs上面的addA是一个方法
  </div>
</template>

<script setup lang="ts">
import {  } from 'vue'

defineProps(['a'])
</script>
<style lang="scss" scoped>

</style>

六、$refs、$parent:父<->子通信

注意:此种方式只能在组件模板中拿到$refs和$parent的值。并且$refs获取不到孙组件

1、$refs获取所有子组件 

父组件 :在组件模板中拿到$refs并当做参数传递使用

<template>
  <div class="">
    <p>父组件sum值:{{ sum }}</p>
    <button @click="getAllRefs($refs)">获取所有子组件ref</button>
    <Children ref="c1"/>
    <Children2 ref="c2"/>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import Children from "./children.vue";
import Children2 from "./children2.vue";
let c1 = ref()
let c2 = ref()
let sum = ref(1)
function getAllRefs(refs:any){// 调用方法时需要传 $refs
  console.log(refs,'所有子组件');
  // 可以直接通过 refs.子组件名来操作子组件暴露出来的数据
}
// 暴露数据
defineExpose({sum})
</script>
<style lang="scss" scoped>

</style>

2、$parent获取父组件

<template>
  <div class="">
    <p>子组件sum值:{{ sum }}</p>
    <button @click="getParent($parent)">获取父组件</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
let toy = ref('奥特曼')

function getParent(parent:any){// 调用方法时需要传 $parent
  console.log('父组件',parent);
  // 可以直接通过 parent.属性名 来操作父组件暴露出的数据
}
// 暴露数据
defineExpose({toy})
</script>

七、provide-inject:父->子->孙

说明:父组件通过provide暴露数据,任意一级子组件都可以直接通过inject获取数据,数据为响应式

 1、provide传递数据

注意:通过provide传递ref定义的数据时,不要加 .value 否则数据会失去响应式

import { provide, reactive } from 'vue'
import Children from "./children.vue";
let info = reactive({
  label:'父组件',
  str:'数据'
})
function changeInfo(){
  info.str += '-小猪'
}
//格式 provide('参数名',参数值)
provide('provideData',{info,changeInfo})

 2、任意子组件通过inject接收数据

// 格式 inject('接收的参数名',参数的默认值) // 默认值可有可无 有函数或对象类型时建议写
// let {info,changeInfo} =inject('parentData')
let {info,changeInfo} = inject('parentData',{info:{str:'',label:''},changeInfo:()=>{}})

function changParentInfo(){
  // 可以直接对接收到的值进行修改,数据是响应式的
  info.str+='-大猪'
}

八、slot

1、默认插槽

父组件-在子组件标签中编写需要插入的代码

<Category>
  <p>数据</p>
</Category>

 子组件-写slot标签标识插槽的位置(如果父组件未传递插槽内容,就会显示slot中的默认内容)

<template>
  <div class="">
    <slot><p>默认内容</p></slot>
  </div>
</template>

 2、具名插槽

父组件 :给插槽内容命名,插入到指定name的slot标签中,如果没有对应name的标签就不插入

// 命名方式 v-slot:插槽名 或 #插槽名
// 写法一:直接在组件标签上命名  不推荐
<Category #:cName>
  <p>数据1</p>
</Category>
// 写法二:在template上命名
<Category>
  <template #:cName>
    <p>数据2</p>
  </template>
  <template #:xxx>
    <p>数据2</p>
  </template>
</Category>

子组件:给slot标签加上name作为标识

<template>
  <div class="">
    <slot name="xxx"><p>默认内容</p></slot>
  </div>
  <div class="">
    <slot name="cName"><p>默认内容</p></slot>
  </div>
</template>

3、插槽传值:子->父

子组件 

<template>
  <div class="category">
    <div class="content">
      <slot name="c1" :str="str" a="哈哈">c1默认内容</slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

let str = ref('字符串str')

</script>

父组件 

<Category title="热门城市">
  <template #c2="params">
    <p>插槽传递的参数:{{ params }}</p> //params={ "str": "字符串str", "a": "哈哈" }
  </template>
</Category>

九、Pinia:任意组件通信

1、安装 npm install pinia

2、引入

在main.ts文件中修改

import { createApp } from "vue";
import App from "./App.vue";

import { createPinia } from "pinia";
const pinia = createPinia()

const myApp = createApp(App)
myApp.use(pinia)
myApp.mount('#app')

3、创建/src/store/xxx.ts

①、基础写法

import { defineStore } from "pinia";

// 基础写法
export const useCountStore = defineStore('count',{
  state(){
    return {
      sum:6,//在组件中使用时可以直接修改
    }
  },
  getters:{
    bigSum(state){
      return state.sum*3
    }
  },
  actions:{
    addSum(val:number){
      this.sum+=val
    },
  },
})

②、进阶写法(常用)

import { defineStore } from "pinia";
import { ref } from 'vue'
export default defineStore('text',()=>{
  let sum = ref(6)
  function addSum(val:number){
    sum.value+=val
  }
  let bigSum = computed(()=>{
    return sum.value*3
  })
  return {sum,addSum,bigSum }
})

4、在代码中使用

父组件

<template>
  <div class="">
    <h3>Pinia</h3>
    <p>当前sun值:{{ sumStore.sum }}。bigSum:{{sumStore.bigSum}}</p>
    <childrenCount/>
  </div>
</template>

<script setup lang="ts">
import childrenCount from "./children/08-pinia-count.vue";
import childrenText from "./children/08-pinia-text.vue";
import useSumStore from "@/store/count";
import { ref,reactive } from "vue";
const sumStore = useSumStore ()
// 监听store中的数据变化,类似于watch
sumStore .$subscribe((mutate,state)=>{
  // mutate:本次修改数据,state:store中的state
  console.log(mutate,state,'数据变化了');
})

</script>

子组件文章来源地址https://www.toymoban.com/news/detail-824886.html

<template>
  <div class="">
    <h4>组件一</h4>
    <button @click="addSum">增加sum值</button>
    <button @click="jianSum">减少sum值</button>
  </div>
</template>

<script setup lang="ts">
import { useCountStore } from "@/store/count";
import { storeToRefs } from "pinia";
const countStore = useCountStore()
// 解构pinia中的数据时,使用 storeToRefs
let {sum} = storeToRefs(countStore)

function addSum(){
  // 可以直接修改通过pinia定义的数据
  // 第一种修改方式  单个修改
  // countStore.sum++
  // 第二种修改方式  批量修改
  // countStore.$patch({
  //   sum:9,
  // })
  countStore.addSum(3)
}
function jianSum(){
  sum --
}
</script>

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

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

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

相关文章

  • vue3-父子组件间通信

    在实际业务开发的过程中,我们时常会遇到组件间的通信问题,比如:父子组件间通信、同级组件间通信等。本篇文章中主要介绍父子组件间通信。父子组件间通信主要有以下常见形式: 方案 父组件向子组件 子组件向父组件 props/emits props emits v-model/emits v-model emits ref/emits

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

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

    2024年02月09日
    浏览(43)
  • Vue3 组件之间的通信

    经过前面几章的阅读,相信开发者已经可以搭建一个基础的 Vue 3 项目了! 但实际业务开发过程中,还会遇到一些组件之间的通信问题,父子组件通信、兄弟组件通信、爷孙组件通信,还有一些全局通信的场景。 这一章就按使用场景来划分对应的章节吧,在什么场景下遇到问

    2023年04月08日
    浏览(43)
  • vue3组件通信之pinia

      在vue3,vue的状态管理也迎来了新的变更,在vue3使用新的组件pinia来代理原有的vuex。pinia相比vuex,功能收敛了不少,比如不直接暴露setter方式,外部直接修改数据 vuex:集中式管理状态容器,可以实现任意组件之间通信 核心概念:state、mutations、actions、getters、modules pinia:集中式

    2024年02月11日
    浏览(40)
  • vue3 快速入门系列 —— 组件通信

    组件通信在开发中非常重要,通信就是你给我一点东西,我给你一点东西。 本篇将分析 vue3 中组件间的通信方式。 Tip :下文提到的绝大多数通信方式在 vue2 中都有,但是在写法上有一些差异。 在 vue3 基础上进行。 新建三个组件:爷爷、父亲、孩子A、孩子B,在主页 Home.vu

    2024年04月17日
    浏览(62)
  • 【vue3】学习笔记--组件通信方式

    学习vue3总是绕不开vue2 vue3组件通信方式如下: props数据只读,从父组件传递到子组件,子组件内部不可直接更改 子组件需要使用defineProps方法接受父组件传递过来的数据 setup语法糖下局部组件无需注册直接可以使用 父组件 子组件 vue框架中事件分为两种:原生的DOM事件和自定

    2024年02月13日
    浏览(48)
  • Vue3组件间的通信方式

    目录  1.props父向子组件通信 2.自定义事件 子向父组件通信 3.全局事件总线 4.v-model组件通信(父子组件数据同步) 绑定单个数据同步  绑定多个数据同步  5.useAttrs组件通信  6.ref与$parent ref获取子组件实例对象  $parent获取父组件实例对象  7.provide-inject 可以实现隔辈传输 8.

    2024年02月17日
    浏览(43)
  • VUE3+TS(父子、兄弟组件通信)

    目录 父传子值、方法(子调用父值、方法) 子传父值(父调用子值) 父读子(子传父)(父调用子值、方法) 兄弟(任意组件)通信 引入Mitt来完成任意组件通信 1、统一规范写法,通过在子组件标签上绑定属性和值,来传递到子组件,子组件再通过defineProps来接收,先给其

    2023年04月08日
    浏览(47)
  • vue3探索——组件通信之事件总线

    Vue2.x使用EventBus进行组件通信,而Vue3.x推荐使用 mitt.js 。 比起Vue实例上的 EventBus , mitt.js 好在哪里呢?首先它足够小,仅有200bytes,其次支持全部事件的监听和批量移除,它还不依赖Vue实例,所以可以跨框架使用,React或者Vue,甚至jQuery项目都能使用同一套库。 使用yarn安装

    2024年02月12日
    浏览(44)
  • vue3探索——组件通信之依赖注入

    通常情况下,当我们需要从父组件向子组件传递数据时,会使用  props 。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递

    2024年02月10日
    浏览(40)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包