Vue3 组件通信方式
1. Props(父组件给子组件传递数据)
子组件
<template> <div style="height:100px;background-color: yellow"> <div>{{text}}</div> <div>{{props.text}}</div> </div> </template> <script setup> let props=defineProps(["text"]) console.log(props) </script>
子组件需要使用到defineProps方法去接受父组件传递过来的数据,defineProps是vue3提供方法,不需要引入直接使用,props为代理对象,在模板中使用可以{{props.属性名}}或者{{直接属性名}}进行使用。当然在<script>标签中获取属性名的值只能props.属性名。并且这里的props代理对象仅仅只是可读的,不可以修改。
父组件
<template> <div style="height:200px;background-color: red"> <son :text="text"></son> </div> </template> <script setup> import son from './Son.vue' import {ref} from "vue" let text=ref("hello") </script>
2. 自定义事件 (子组件给父组件传递数据)
在vue框架中事件分为两种:一种是原生的DOM事件,另外一种自定义事件。
原生DOM事件可以让用户与网页进行交互,比如click、dbclick、change.mouseenter自定义事件,可以实现子组件给父组件传递数据。在vue3框架click、dbclick、change(这类原生DOM事件).不管是在标签、自定义标签上(组件标签)都是原生DOM事件。
子组件
<template> <div style="height:100px;background-color: yellow"> <button @click="handle">点击触发</button> </div> </template> <script setup> //利用defineEmits方法返回函数触发自定义事件,defineEmits方法不需要引入直接使用 let emit=defineEmits(['xxx']) const handle=()=>{ // 第一个参数:事件类型第二个|三个|N参数即为注入数据 emit('xxx','hello') } </script>
父组件
<template> <div style="height:200px;background-color: red"> <son @xxx="hander"></son> </div> </template> <script setup> import son from './Son.vue' import {ref} from "vue" const hander=(param)=>{ alert(param) } </script>
3. v-model
父组件
<template> <div style="height:200px;background-color: red"> <son v-model:text="text"></son> </div> </template> <script setup lang="ts"> import son from './Son.vue' import {ref} from "vue" let text=ref("hello") </script>
子组件
<template> <div style="height:100px;background-color: yellow"> <div>{{text}}</div> <el-button @click="handle">点击</el-button> </div> </template> <script setup lang="ts"> let props=defineProps(["text"]) let emit=defineEmits(["update:text"]) const handle=()=>{ emit("update:text","20") } </script>
4. ref和$parent
父组件控制子组件
父组件
<template> <div style="height:100px;background-color: yellow"> <div>{{money}}</div> <el-button @click="handle">父组件金钱加10,子组件金钱减10</el-button> <son ref="son1"></son> </div> </template> <script setup lang="ts"> import son from "./Son.vue" import {ref} from "vue" let son1=ref() let money=ref(100) const handle=()=>{ money.value+=10 son1.value.money-=10 } </script>
子组件
<template> <div style="height:100px;background-color: yellow"> <div>{{money}}</div> </div> </template> <script setup lang="ts"> import {ref} from "vue" let money=ref(80) //组件内部数据对外关团的,别人不能访问 //如果想让外部访问需要通过defineExpose方法对外暴露 defineExpose({ money }) </script>
子组件控制父组件
父组件
<template> <div style="height:100px;background-color: yellow"> <div>{{money}}</div> <son></son> </div> </template> <script setup lang="ts"> import son from "./Son.vue" import {ref} from "vue" let money=ref(100) //组件内部数据对外关团的,别人不能访问 //如果想让外部访问需要通过defineExpose方法对外暴露 defineExpose({ money }) </script>
子组件
<template> <div style="height:100px;background-color: yellow"> <div>{{money}}</div> <el-button @click="handle($parent)">父组件金钱加10,子组件金钱减10</el-button> </div> </template> <script setup lang="ts"> import {ref} from "vue" let money=ref(80) const handle=(parent)=>{ money.value-=10 // 这里为代理对象 parent.money+=10 } </script>
5. Provide和inject
父节点及以上节点和子孙节点的传值,注意传递获得的数据使用的是同一个对象,一个改变其余的都改变。
父组件
<template> <div style="height:100px;background-color: yellow"> <son></son> </div> </template> <script setup lang="ts"> import son from "./Son.vue" import {ref,provide,reactive} from "vue" let money=ref(100) provide("money",money) </script
子组件
<template> <div style="height:100px;background-color: yellow"> <div>{{money}}</div> </div> </template> <script setup lang="ts"> import {ref,inject} from "vue" let money=inject("money") </script>
6. 插槽
父组件
<template> <div style="height:100px;background-color: yellow"> <son> <div>hello</div> <!-- <template v-slot:text>--> <!-- <div>具名插槽内容</div>--> <!-- </template>--> <template #text> <div>具名插槽内容</div> </template> <template #test="{row}"> <div>{{row.title}}</div> <div>{{row.content}}</div> </template> </son> </div> </template> <script setup lang="ts"> import son from "./Son.vue" import {ref,provide,reactive} from "vue" </script>
子组件
<template> <div style="height:50px;background-color: bisque"> <h>子组件默认插槽</h> <slot></slot> <h>子组件具名插槽</h> <slot name="text"></slot> <h>子组件作用域插槽</h> <slot :row="state" name="test"></slot> </div> </template> <script setup > import {reactive} from "vue" const state=reactive({ title:"hello", content:"good" }) </script>