当前位置: 首页 > news >正文

VUE3(四)、组件通信

1、props

        作用:子组件之间的通信。
父传子:属性值的非函数。
子传父:属性值是函数。

       父组件:

<template><div>{{ childeData }}</div>——————————————————————————————<child :parentData="parentData" :sendData="getChildData"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './childeIndex.vue'const childeData=ref("");
const parentData=ref("parentData");function getChildData(data:string){childeData.value=data;
}</script>

        子组件:

<template><div>{{ parentData }}</div><button @click="sendData(data)"></button>
</template>
<script setup lang="ts" name="child">
import { ref } from 'vue'
defineProps(['parentData','sendData'])const data=ref('aaa')</script>

2、自定义事件

        通过父组件定义函数,子组件调用父组件的函数来实现参数的传递。

        父组件:

<template><div>{{ childeData }}</div>——————————————————————————————<child @send-toy="getChildData"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './childeIndex.vue'const childeData=ref("");function getChildData(data:string){childeData.value=data;
}</script>

        子组件:

<template><div>子组件</div><button @click="sendDat"></button>
</template>
<script setup lang="ts" name="child">import { ref } from 'vue'let data=ref('我是子组件')const emit = defineEmits(['send-toy'])function sendDat(){emit('send-toy',data)}</script>

3、mitt

        实现任意组件的通信。个人理解:在组件与组件之间提供了一个平台,都向这个平台发送、读取数据。
安装步骤:

  1. npm i mitt
  2. 新建文件utiles/emitter.ts
  3. 在需要的文件中引入emitter,进行绑定 事件,或调用事件。
  4.  在文件中进行解绑(unmounted中)

       emitter.ts

import mitt from 'mitt'
const emitter=mitt()
export default emitter

        获取数据的文件

<template><h2>child2中的数据:{{ src }}</h2>
</template>
<script setup lang="ts" name="child1">import { onUnmounted, ref } from 'vue'import emitter from '@/utils/emitter'const src=ref('')//监听事件emitter.on('getData',(data:string)=>{src.value=data})//在组件销毁时取消监听onUnmounted(()=>{emitter.off('getData')})
</script>

        发送数据的文件

<template><h2>child2的数据:{{ data }}</h2><button @click="getdata"> 点击获取数据 </button>
</template>
<script setup lang="ts" name="child2">import { ref } from 'vue'import emitter from '@/utils/emitter'const data = ref('222')function getdata(){emitter.emit('getData',data)}
</script>

4、v-model

        原理:实现双向绑定,通过传递props参数实现父传子,通过emit传递input或者点击事件实现子传父。

        父组件:

<template><!-- 这个写法的本质就是下面那种 --><input type="text" v-model="str"/><input type="text" :value="str" @input="str=(<HTMLInputElement>$event.target).value"/><!-- 自定义组件,一二种方法一致 --><selfInput v-model="str"></selfInput><!-- 此处的$event就是传递的数据 --><selfInput :modelValue="str" @update:modelValue="str=$event"></selfInput></template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import selfInput from './selfInput.vue';let str = ref('');
</script>

        自定义组件(selfInput.vue):

<template><input type="text" :value="modelValue" @input="emit('update:modelValue',($event.target as HTMLInputElement).value)"/>
</template>
<script setup lang="ts" >
import { ref,defineProps,defineEmits } from 'vue';defineProps(['modelValue'])const emit = defineEmits(['update:modelValue'])</script>

如果自定义自定义组件中的名称,可以实现多个组件的双向绑定。

        父组件:

<template>{{ str }} --------{{ pass }}<selfInput v-model:name="str" v-model:pass="pass"></selfInput> 
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import selfInput from './selfInput.vue';let str = ref('');
let pass = ref('');
</script>

        子组件:

<template><input type="text" :value="name" @input="emit('update:name',($event.target as HTMLInputElement).value)"/><input type="text" :value="pass" @input="emit('update:pass',($event.target as HTMLInputElement).value)"/>
</template>
<script setup lang="ts" >
import { ref,defineProps,defineEmits } from 'vue';defineProps(['name','pass'])const emit = defineEmits(['update:name','update:pass'])</script>

5、$attrs

        作用:适用于当前组件,向子组件通信(祖-->孙)。
当父组件给子组件传递参数,且子组件没有使用props进行接收时,所传递的参数存在attrs中。在子组件中使用$attrs就可以获取所有未被接收的数据。

        父组件:

<template><div>{{ a }}</div><hr/><div>{{ b }}</div><hr/><div>{{ c }}</div><hr/><child v-bind="{a,b,c}" @changeA="changeA"></child>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './chile.vue';
let a=ref(1);
let b=ref(2);
let c=ref(3);
function changeA(value:number){a.value=value;
}
</script>

        子组件:

<template><div>{{ a }}</div><hr/>--------------------------------<sun v-bind="$attrs"></sun>
</template>
<script setup lang="ts" name="chile">import sun from './sun.vue'defineProps(['a'])
</script>

        孙组件:

<template><div>{{ b }}</div><hr/><div>{{ c }}</div><hr/><button @click="changeAa">修改a</button>
</template>
<script setup lang="ts" >const num=defineProps(['b','c']);const emit=defineEmits(['changeA']);function changeAa(){emit('changeA',num.b);}
</script>

6、$refs、$parent

        $refs:用于父组件修改子组件中的数据。获取所有子组件暴露的数据。
$parent:用于子组件修改父组件的数据。获取父组件所有暴露的数据。

        以上的前提:使用defineExpose暴露数据。

        父组件:

<template><h1>父组件数据</h1><h1>{{ a }}</h1><button @click="changeChildeA($refs)">修改子组件数据</button><br/>--------------------------------<child1 ref="child1"/>--------------------------------<child2 ref="child2"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child1 from './childe1.vue';
import child2 from './childe2.vue';
let a=ref(1);
function changeChildeA(refs:any){refs.child1.b++;refs.child2.b++;
}
defineExpose({a})
</script>

        子组件1:

<template>    <h1>子组件数据</h1><h1>a:{{ a }}</h1><h1>b:{{ b }}</h1><button @click="changeParent($parent)">修改父组件的a</button>
</template>
<script setup lang="ts" >
import { ref } from 'vue'
let a=ref(1)
let b=ref(1)
function changeParent(parent:any){parent.a++
}
//暴露
defineExpose({b
})
</script>

        子组件2:

<template>    <h1>子组件数据</h1><h1>a:{{ a }}</h1><h1>b:{{ b }}</h1>
</template>
<script setup lang="ts" >
import { ref } from 'vue'
let a=ref(1)
let b=ref(1)//暴露
defineExpose({a,b
})
</script>

7、provide、inject

        作用:实现祖孙组件之间的数据传递。
传递数据:provide(“数据名称”,数据)。
接收数据:inject(“数据名称”,默认值)。

        父组件:

<template><h1>父组件数据</h1><h1>{{ a }}</h1>--------------------------------<child1 ref="child1"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref,provide } from 'vue';
import child1 from './childe1.vue';let a=ref(0);
function changeA(value:number){a.value+=value;
}provide("parent",{a:a,changeA})</script>

        子组件:

<template>    <h1>子组件数据</h1><h1>a:{{ a }}</h1><div><button @click="changeA(1)">更改父组件的a</button></div>
</template>
<script setup lang="ts" >
import { ref,inject } from 'vue'
let {a,changeA} = inject('parent',{a:ref(0),changeA:function(x:number){}})
</script>

8、插槽

        作用:引入组件时可以给组件传递一些HTML元素。        

默认插槽

        父组件中引入子组件时,子组件标签内部的元素就是会传入slot的参数。
子组件中的slot就相当于占位符,给未来传进来的元素预留空位。

        父组件:

<template><h1>父组件数据</h1><div class="child"><child1 :title="'第一个'"><div style="color: aqua;">1111111111</div></child1><child1 :title="'第二个'"><div style="color:black;">22</div></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>
<style scoped>

        子组件:

    <div class="child"><h1 style="color: black;">{{ title }}</h1><slot>默认值</slot></div></template>
<script setup lang="ts" >defineProps(['title'])
</script>

具名插槽

        作用:可以指定元素插入的位置。
用法:在定义插槽位置时,使用name属性定义其名字。
在应用组件时,在其标签或Templet标签内部定义v-slot(或使用#+名字)属性。

        父组件:      

<template><h1>父组件数据</h1><div class="child"><child1 :title="'第一个'"><template #b><div style="color: aqua;">1111111111</div></template></child1><child1 :title="'第二个'"><template #a><div style="color:black;">22</div></template></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>

        子组件:

<template>    <div class="child"><h1 style="color: black;">{{ title }}</h1><slot name="a">默认值</slot><h1>-------------分隔符--------------------</h1><slot name="b">默认值</slot></div></template>
<script setup lang="ts" >defineProps(['title'])
</script>

作用域插槽

        作用:当父组件需要子组件的数据。
用法:在定义slot标签时,使用props写法进行传递参数。
在父组件中使用v-slot拿到参数。
如果同时使用了具名插槽:v-slot:name=‘parms’               

        父组件:

<template><h1>父组件数据</h1><div class="child"><child1 :title="'第一个'"><template #a="{game,a}"><ul><li v-for="item in game" :key="item.id">{{ item.name }}</li></ul></template></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>

       子组件:

<template>    <div class="child"><h1 style="color: black;">{{ title }}</h1><slot name="a" :game="game" :a="a">默认值</slot></div></template>
<script setup lang="ts" >
import { reactive } from 'vue'; defineProps(['title'])const game=reactive([{id:1,name:'a'},{id:2,name:'b'},])const a=1;
</script>

http://www.dtcms.com/a/301488.html

相关文章:

  • 1439-素数环2
  • 基于深度学习的图像分割:使用DeepLabv3实现高效分割
  • QT6 源,七章对话框与多窗体(17)用于辅助多文档 MDI 窗体设计 QMdiArea 的类 QMdiSubWindow:
  • [10月考试] B
  • 3.5-非关系型数据库-反规范化-sql语言
  • 市电有电检测电路
  • [硬件电路-96]:什么是闭环反馈?什么是闭环正反馈控制?什么是闭环负反馈控制?
  • RK3568 Linux驱动学习——Linux驱动开发准备工作
  • 企业IT管理——突发病毒事件应急处理预案模板
  • 永磁同步电机控制算法--弱磁控制(虚拟电阻)
  • 51c大模型~合集160
  • 重温经典,小巧方便的 WinXP 来啦!提供离线驱动
  • 【编号444】雅鲁藏布江(上中下)游8级水系湖泊数据合集
  • net8.0一键创建支持(RabbitMQ)
  • 神经网络知识讨论
  • 嵌入式硬件篇---驱动板
  • 【学习笔记】DexMimicGen:通过模仿学习实现双臂灵巧操作的自动化数据生成
  • 数据结构基础内容(第三篇:堆栈)
  • 深度解析 inaSpeechSegmenter:高效音频语音分割与检测开源工具
  • Epoll事件EPOLLRDHUP详解
  • springboot基于Java与MySQL库的健身俱乐部管理系统设计与实现
  • C51:使用超声波测量距离
  • C#.NET dapper 详解
  • MySQL 中的 BufferPool 和 ChangeBuffer
  • Amazon Relational Database Service (Amazon RDS)入门课
  • 量子力学的基本假设
  • 【Java】图书管理系统设计详解
  • 《 集成异步任务与定时调度:线程池与任务中心设计》
  • C++--继承
  • 设计模式(六)创建型:单例模式详解