vue3组件间通信

1.props

父组件引入子组件,并在其中传递相关数据

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

子组件用defineProps进行接收

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

<script setup lang="ts">
//需要使用到defineProps方法去接受父组件传递过来的数据
//defineProps是Vue3提供方法,不需要引入直接使用
let props = defineProps(['info','money']); //数组|对象写法都可以
</script>

props数据只读,模板中可省略对象名,直接写属性。而script中必须用**.属性


2.自定义事件

2.1.原生dom事件

模板中写一行数据,并在标签中写下点击事件handler

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

向事件回调注入事件对象

<script setup lang="ts">
    //事件回调--1
const handler = (event)=>{
    //event即为事件对象
    console.log(event);
}
</script>

也可以在其中传递多个参数

模板中

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

事件回调中进行数据接收

<script setup lang="ts">
//事件回调--2
const handler1 = (a,b,c,$event)=>{
   console.log(a,b,c,$event)
}
</script>

2.2.自定义事件

引入子组件,并在子组件中加入点击事件,其中vue2与vue3对其事件定义不一致

<!--
        vue2框架当中:这种写法自定义事件,可以通过.native修饰符变为原生DOM事件
        vue3框架下面写法其实即为原生DOM事件

        vue3:原生的DOM事件不管是放在标签身上、组件标签身上都是原生DOM事件
      -->
    <Event1 @click="handler2"></Event1>
<script setup lang="ts">
//引入子组件
import Event1 from './Event1.vue';

//事件回调---3
const handler2 = ()=>{
    console.log(123);
}

</script>

其中绑定的事件是给子组件的根节点绑定的


父组件中,子组件绑定自定义事件

    <!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
    <Event2 @xxx="handler3" @click="handler4"></Event2>
<script setup lang="ts">
//引入子组件
import Event1 from './Event1.vue';

//事件回调---4
const handler3 = (param1,param2)=>{
    console.log(param1,param2);
}

//事件回调--5
const handler4 = (param1,param2)=>{
     console.log(param1,param2);
}
</script>

子组件中

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

利用defineEmits方法返回函数触发自定义事件
defineEmits方法不需要引入直接使用
如:

let $emit = defineEmits(['xxx','click']);
按钮点击回调中第一个参数:事件类型 第二个|三个|N参数即为注入数据

$emit('xxx','东风导弹','航母');

其中,父组件handler4事件原为原生dom事件,但是子组件在用defineEmits引入点击事件后vue3认为点击事件已成为自定义事件,所以要想handler4事件执行,必须把事件回调重新写入,同子组件handler一样写个事件回调,或者直接把$emit('click','AK47','J20')作为事件click后的属性值。


3.全局事件总线

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

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

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

可以使用插件mitt实现。

mitt:官网地址:https://www.npmjs.com/package/mitt

$  npm install --save mitt


//using ES6 modules
import mitt from 'mitt' //方法在执行会返回bus对象


//usage
const emitter = mitt()

// listen to an event
emitter.on('foo', e => console.log('foo', e) )

// listen to all events
emitter.on('*', (type, e) => console.log(type, e) )

// fire an event
emitter.emit('foo', { a: 'b' })

// clearing all events
emitter.all.clear()

// working with handler references:
function onFoo() {}
emitter.on('foo', onFoo)   // listen
emitter.off('foo', onFoo)  // unlisten

以上是官网查询的用法。可以看出其有着欧onemit两种方法

我们可以在src文件夹下建立bus文件夹,再建立index.ts文档

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

需要绑定接收数据的组件内引用

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

传递数据的组件内,在事件回调中用emit先写所需触发的事件,再写数据对象。

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

4.v-model

v-model指令:收集表单数据,数据双向绑定

v-model也可以实现组件之间的通信,实现父子组件数据同步的业务

父亲给子组件数据 props

子组件给父组件数据 自定义事件

父组件内引入子组件,并绑定一个数据

<template>
  <div>
    <h1>v-model:钱数{{ money }}</h1>
    <input type="text" v-model="info" />
    <hr />
    <!-- props:父亲给儿子数据 -->
    <Child :modelValue="money" @update:modelValue="handler"></Child>
    <!-- 
        @*中:可换为其他数值字母
     -->
    <hr />
  </div>
</template>

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

子组件内用defineProps接收数据

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

父组件内子组件绑定自定义事件。当子组件内绑定数据更新事件时,数据传向父组件。父组件若要实现数据增减同步改变的时候,其事件回调中需要接受传来的数据,


当然,v-model再组件身上使用时

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

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

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

v-model还有一种语法

就是在父组件定义pageNo,pageSize两个数据,并且在其引入的子组件内,用v-model绑定一个单独属性名,属性值为所定义两个数据

<template>
    <Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
</template>


<script setup lang="ts">
//v-model指令:收集表单数据,数据双向绑定
//v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
//父亲给子组件数据 props
//子组件给父组件数据 自定义事件
//引入子组件
import Child1 from "./Child1.vue";
import { ref } from "vue";
//父亲的数据
let pageNo = ref(1);
let pageSize = ref(3);
</script>

子组件内

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

'update:属性名'是在v-model进行绑定数据后,自动创建的自定义事件,若想要对数据进行操作,可defineEmits接收相应的自定义事件,并在所需标签内绑定事件,在事件回调内写入相关操作。


5.useAttrs

vue3框架提供一个方法useAttrs方法,它可以获取组件身上的属性与事件!!! 

类似于props,但优先级相对较低

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

父组件内(app组件内已经安装引入了elment ui)

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

子组件用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>

其得到代理对象,如果用props接收数据,则useAttrs上就没有该数据,props优先级更高


6.ref与$parent

ref:可以获取真实的DOM节点,可以获取到子组件实例VC

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

父组件

<template>
  <div class="box">
    <h1>我是父亲曹操:{{money}}</h1>
    <button @click="handler">找我的儿子曹植借10元</button>
    <hr>
    <Son ref="son"></Son>
    <hr>
    <Dau></Dau>
  </div>
</template>

<script setup lang="ts">
//ref:可以获取真实的DOM节点,可以获取到子组件实例VC
//$parent:可以在子组件内部获取到父组件的实例
//引入子组件
import Son from './Son.vue'
//女儿组件,在使用$parent时会进行导入,这里只是提前导入了
import Dau from './Daughter.vue' 
import {ref} from 'vue';
//父组件钱数
let money = ref(100000000);
//获取子组件的实例
let son = ref();
//父组件内部按钮点击回调
const handler = ()=>{
   money.value+=10;
   //儿子钱数减去10
   son.value.money-=10;
   son.value.fly();
}
//对外暴露
defineExpose({
   money
})
</script>

子组件

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

父组件中引入的子组件,用ref='son',并且在script标签内获取子组件的实例let son = ref();

但是,对于组件来说,他的数据的默认关闭的不对外暴露

所以,就算父组件拿到了子组件实例,却拿不到子组件的数据

若需要让外部访问则应该用defineExpose方法对外暴露

数据与方法在对外暴露都可以使用


女儿组件

<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)=>{
   money.value+=10000;
   $parent.money-=10000;
}
</script>

女儿组件在点击按钮时注入$parent,这可以获取到其父组件的实例

当然,父组件还是得对外暴露他的数据,不然女儿组件无法拿到相关的数据


7.provide与inject

vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据

祖先组件给后代组件提供数据有两个参数:

        第一个参数就是提供的数据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>

子组件

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

<script setup lang="ts">
import Child from './GrandChild.vue';
</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>

祖先用$parent('自定义key',数据)将数据提供,

子代组件用引入inject,将数据注入组件内。

注入时,需要的是祖先提供的自定义key值,然后其会返回祖先提供的数据。

子代组件可以通过事件进行修改父组件所传过来的数据


8.pinia

vuex:集中式管理状态容器,可以实现任意组件之间通信!!!

核心概念:state、mutations、actions、getters、modules

pinia:集中式管理状态容器,可以实现任意组件之间通信!!!

核心概念:state、actions、getters

pinia写法:选择器API、组合式API

父组件

<template>
  <div class="box">
    <h1>pinia</h1>
    <div class="container">
      <Child></Child>
      <Child1></Child1>
    </div>
  </div>
</template>

<script setup lang="ts">
import Child from "./Child.vue";
import Child1 from "./Child1.vue";
//vuex:集中式管理状态容器,可以实现任意组件之间通信!!!
//核心概念:state、mutations、actions、getters、modules

//pinia:集中式管理状态容器,可以实现任意组件之间通信!!!
//核心概念:state、actions、getters
//pinia写法:选择器API、组合式API
</script>

子组件

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

子组件1

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

<script setup lang="ts">
import useInfoStore from "../../store/modules/info";
//获取小仓库对象
let infoStore = useInfoStore();

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

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

src文件夹下建立一个仓库文件夹store

index.ts

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

当然必须得到入口文件main.ts引入这个仓库

//引入仓库
import store from './store'

再建立两个小仓库

info.ts(选择式api)

//定义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: {
        total() {
            let result:any = this.arr.reduce((prev: number, next: number) => {
                return prev + next;
            }, 0);
            return result;
        }
    }
});
//对外暴露方法
export default useInfoStore;

todo.ts(组合式api)

//定义组合式API仓库
import { defineStore } from "pinia";
import { ref, computed,watch} 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, next) => {
            return prev + next;
        }, 0)
    })
    //务必要返回一个对象:属性与方法可以提供给组件使用
    return {
        todos,
        arr,
        total,
        updateTodo() {
            todos.value.push({ id: 4, title: '组合式API方法' });
        }
    }
});

export default useTodoStore;

defineStore方法用于定义小仓库,其需要传递两个参数:

        第一个仓库:小仓库名字  

        第二个参数:小仓库配置对象

defineStore方法执行会返回一个函数,函数作用就是让组件可以获取到仓库数据

函数写法,return返回的对象才是提供的数据

子组件引入仓库,接收数据所返回的对象(想用就导入仓库,一旦某一组件修改了所接受的仓库数据,那么仓库数据也被修改,所导入仓库的组件数据也会被修改

可直接修改数据,做到组件间通信,也可用所接受仓库对象上的方法$patch进行数据修改

const updateCount = () =>{
    infoStore.$patch({
        count:1111
    })
    console.log(infoStore);
};

也可在仓库中定义方法,组件导入仓库后直接使用进行修改所需数据,类似于$patch

(注意:函数没有context上下文对象)

可在定义的方法内注入一些参数

仓库

actions:{
    
    updateNum(a:number,b:number){
        console.log(a,b);
        this.count++;
    }
},

组件内如上(子组件)代码,添加了两个参数

仓库里用this,返回该仓库对象,可用this里的方法进行修改数据

(没有commit、没有mutations去修改数据)\


todo.ts是采用组合式api的写法,定义小仓库的方法和上面info.ts一样,引用vue下的ref函数或者reactive函数,使数据成为响应式(得在return外创建数据,实现响应式),组件导入数据依旧和info.ts一样

return里面创建相关方法,若要计算方法,则导入vue中的computed,在return外进行相关计算

主要是运用的vue中组合式api的函数


9.插槽

9.1.默认插槽

SlotTest.vue

<template>
  <div>
    <h1>slot</h1>
    <Test>
      <div>
        <pre>大江东去浪淘尽,千古分流人物</pre>
      </div>
    </Test>
  </div>
</template>

<script setup lang="ts">
import Test from "./Test.vue";
//插槽:默认插槽、具名插槽、作用域插槽
//作用域插槽:就是可以传递数据的插槽,子组件可以讲数据回传给父组件,父组件可以决定这些回传的
//数据是以何种结构或者外观在子组件内部去展示!!!

</script>

Test.vue

<template>
  <div class="box">
    <h1>我是子组件默认插槽</h1>
    <!-- 默认插槽 -->
    <slot></slot>
  </div>
</template>

子组件内用<slot></slot>标签,设置所需插入页面的位置,父组件在引入的子组件内加入所要插入子组件的内容和格式(标签所带格式都会保存)

9.2.具名插槽

SlotTest.vue

<template>
  <div>
    <h1>slot</h1>
    <Test>
      <!-- 具名插槽填充a -->
      <template #a>
        <div>我是填充具名插槽a位置结构</div>
      </template>
      <!-- 具名插槽填充b v-slot指令可以简化为# -->
      <template #b>
        <div>我是填充具名插槽b位置结构</div>
      </template>
    </Test>
  </div>
</template>

<script setup lang="ts">
import Test from "./Test.vue";
//插槽:默认插槽、具名插槽、作用域插槽
//作用域插槽:就是可以传递数据的插槽,子组件可以讲数据回传给父组件,父组件可以决定这些回传的
//数据是以何种结构或者外观在子组件内部去展示!!!

</script>

Test.vue

<template>
  <div class="box">
    <h1>具名插槽填充数据</h1>
    <slot name="a"></slot>
    <h1>具名插槽填充数据</h1>
    <h1>具名插槽填充数据</h1>
    <slot name="b"></slot>
    <h1>具名插槽填充数据</h1>
  </div>
</template>

子组件对<slot name='a'></slot>的name属性值进行修改,父组件内所导入的子组件里,若是标签有相同的#属性值,则该标签内的所有内容都会插入子组件<slot name='属性值'></slot>相关位置内.

父组件内所导入的子组件里标签内v-slot:a'等价于 #a

9.3.作用域插槽

SlotTest.vue

<template>
  <div>
    <h1>slot</h1>
    <Test1 :todos="todos">
      <template v-slot="{ $row, $index }">
        <p :style="{ color: $row.done ? 'green' : 'red' }">
          {{ $row.title }}--{{ $index }}
        </p>
      </template>
    </Test1>
  </div>
</template>

<script setup lang="ts">
import Test1 from "./Test1.vue";
//插槽:默认插槽、具名插槽、作用域插槽
//作用域插槽:就是可以传递数据的插槽,子组件可以讲数据回传给父组件,父组件可以决定这些回传的
//数据是以何种结构或者外观在子组件内部去展示!!!

import { ref } from "vue";
//todos数据
let todos = ref([
  { id: 1, title: "吃饭", done: true },
  { id: 2, title: "睡觉", done: false },
  { id: 3, title: "打豆豆", done: true },
  { id: 4, title: "打游戏", done: false },
]);
</script>

Test1.vue

<template>
  <div class="box">
    <h1>作用域插槽</h1>
    <ul>
      <li v-for="(item, index) in todos" :key="item.id">
        <!--作用域插槽:可以讲数据回传给父组件-->
        <slot :$row="item" :$index="index"></slot>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
//通过props接受父组件传递数据
defineProps(["todos"]);
</script>

作用域插槽:就是可以传递数据的插槽,子组件可以讲数据回传给父组件,父组件可以决定这些回传的
数据是以何种结构或者外观在子组件内部去展示!!!

 <!--作用域插槽:可以讲数据回传给父组件-->

v-for="(item, index) in todos" :key="item.id"  v-for 进行遍历,关键值为其id

:$row="item" 为插槽语法,可将数据回传给父组件

:$index="index"  $index为每条数据的索引值

未完待续,持续更新(仅自用笔记)

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中的组件间通信可以通过props、emit、provide/inject、ref等方式实现。以下是一些示例代码: 1. 使用props和emit进行父子组件间通信: 父组件模板: ``` <template> <ChildComponent :message="parentMessage" @update-message="updateParentMessage" /> </template> ``` 父组件逻辑: ``` import { defineComponent, ref } from 'vue' import ChildComponent from './ChildComponent.vue' export default defineComponent({ components: { ChildComponent }, setup() { const parentMessage = ref('Hello from parent') const updateParentMessage = (message) => { parentMessage.value = message } return { parentMessage, updateParentMessage } } }) ``` 子组件模板: ``` <template> <div> <p>{{ message }}</p> <button @click="updateMessage">Update message</button> </div> </template> ``` 子组件逻辑: ``` import { defineComponent, props, emit } from 'vue' export default defineComponent({ props: { message: String }, setup(props) { const updateMessage = () => { emit('update-message', 'Hello from child') } return { updateMessage } } }) ``` 2. 使用provide/inject进行祖先组件向后代组件传递数据: 祖先组件逻辑: ``` import { defineComponent, provide } from 'vue' import ChildComponent from './ChildComponent.vue' export default defineComponent({ components: { ChildComponent }, setup() { const message = 'Hello from ancestor' provide('message', message) } }) ``` 后代组件逻辑: ``` import { defineComponent, inject } from 'vue' export default defineComponent({ setup() { const message = inject('message') return { message } } }) ``` 3. 使用ref进行父子组件间通信: 父组件模板: ``` <template> <ChildComponent ref="childComponentRef" /> </template> ``` 父组件逻辑: ``` import { defineComponent, ref } from 'vue' import ChildComponent from './ChildComponent.vue' export default defineComponent({ components: { ChildComponent }, setup() { const childComponentRef = ref() const updateChildMessage = (message) => { childComponentRef.value.updateMessage(message) } return { childComponentRef, updateChildMessage } } }) ``` 子组件逻辑: ``` import { defineComponent, ref } from 'vue' export default defineComponent({ setup() { const message = ref('Hello from child') const updateMessage = (newMessage) => { message.value = newMessage } return { message, updateMessage } } }) ``` 以上是一些常见的组件间通信方式的示例代码,具体应该根据实际需求选择合适的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值