Vue3组件通信相关内容整理

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

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

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

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

父组件



子组件 




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

// 父组件
// 子组件
// 通过 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接收到的参数是只读

父组件 



子组件 

// 子组件  在子组件中不对父组件传递的参数做任何操作
// 传递的方法值不在页面中显示 但是可以直接通过 $attrs.方法名 调用



孙组件




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

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

1、$refs获取所有子组件 

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




2、$parent获取父组件



七、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、默认插槽

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


  

数据

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

 2、具名插槽

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

// 命名方式 v-slot:插槽名 或 #插槽名
// 写法一:直接在组件标签上命名  不推荐

  

数据1

// 写法二:在template上命名

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

3、插槽传值:子->父

子组件 



父组件 


  

九、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、在代码中使用

父组件




子组件



你可能感兴趣的:(前端,vue.js,typescript)