自学内容网 自学内容网

Vue3 组件通信

学习总结

props

rops是使用频率最高的一种通信方式,常用于:父<->子
● 若父传子:属性值是非函数
● 若子传父:属性值是函数

<div class="father">
     <h3>父组件</h3>
     <h4>汽车:{{ car }}</h4>
     <h4 v-show="toy">子给父的玩具:{{ toy }}</h4>
     <Child :car="car" :sendToy="getToy"></Child>
 </div>


import Child from './Child.vue';
import { ref } from 'vue';

let car = ref('奔驰')
let toy = ref('')

function getToy(value: string) {
    toy.value = value
}
</script>

<style lang="scss" scoped>
.father {
    width: 100%;
    background-color: pink;
}
<div class="child">
    <h3>子组件</h3>
    <h4>玩具:{{ toy }}</h4>
    <h4>父给的车:{{ car }}</h4>
    <button @click="sendToy(toy)">把玩具给父亲</button>
</div>


import { ref } from 'vue'

let toy = ref('奥特曼')

defineProps(['car', 'sendToy'])

自定义事件

<div class="father">
    <h3>父组件</h3>
    <h4 v-show="toy">子给父的玩具:{{ toy }}</h4>
    <Child @send-toy="saveToy"></Child>
</div>


import Child from './Child.vue';
import { ref } from 'vue';

let toy = ref('')
function saveToy(value:string){
    console.log('saveToy',value);
    toy.value = value
}
<div class="child">
    <h3>子组件</h3>
    <h4>玩具:{{ toy }}</h4>
    <button @click="emit('send-toy',toy)">测试</button>
</div>


import { ref } from 'vue'

let toy = ref('小汽车')

const emit = defineEmits(['send-toy'])

mitt(全局事件总线)

安装
npm install --save mitt
基本使用

// 引入
import mitt from 'mitt'

// 调用mitt得到emitter,emitter能绑定事件、触发事件
const emitter = mitt()

emitter.on('test1', ()=>{
    console.log('test1调用');
})

emitter.on('test2', () => {
    console.log('test2调用');
})

// 触发事件
setInterval(()=>{
    emitter.emit('test1')
    emitter.emit('test2')
},1000)

setTimeout(()=>{
    emitter.all.clear()
},5000)

// 暴露emitter
export default emitter

v-model

1. 单个数据绑定

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

2. 多个数据绑定

<Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
//父亲的数据
let pageNo = ref(1)
let pageSize = ref(3)
<div class="child2">
  <h1>同时绑定多个v-model</h1>
  <button @click="handler">pageNo{{ pageNo }}</button>
  <button @click="$emit('update:pageSize', pageSize + 4)">
    pageSize{{ pageSize }}
  </button>
</div>

let props = defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits(["update:pageNo", "update:pageSize"]);
//第一个按钮的事件回调
const handler = () => {
  $emit("update:pageNo", props.pageNo + 3);
};

$attrs

  1. 概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(祖->孙)
  2. 具体说明:$ attrs是一个对象,包含所有父组件传入的标签属性,
    注意:$attrs会自动排除props中声明的属性(可以认为声明过的props被子组件自己“消费了”)
<div class="father">
    <h3>父组件</h3>
    <h4>a: {{ a }}</h4>
    <h4>b: {{ b }}</h4>
    <h4>c: {{ c }}</h4>
    <h4>d: {{ d }}</h4>
    <Child :a="a" :b="b" :c="c" :d="d" :updateA="updateA"></Child>
</div>


import Child from './Child.vue';
import { ref } from 'vue';

let a = ref(1)
let b = ref(2)
let c = ref(3)
let d = ref(4)

function updateA (value:number) {
    a.value += value
}
<div class="child">
     <h3>子组件</h3>
     <h4>其他:{{ $attrs }}</h4>
     <GrandChild v-bind="$attrs"></GrandChild>
</div>


import { ref } from 'vue'
import GrandChild from './GrandChild.vue';
<div class="grand-child">
    <h3>孙组件</h3>
    <h4>a: {{ a }}</h4>
    <h4>b: {{ b }}</h4>
    <h4>c: {{ c }}</h4>
    <h4>d: {{ d }}</h4>
    <button @click="updateA(6)">点我爷爷那a更新</button>
</div>

defineProps(['a','b','c','d','updateA'])

ref与$parent

1. ref

获取真实的DOM节点,可以获取到子组件实例VC,在父组件中拿到子组件的实例,那么就可以操作子组件的属性及方法了,默认情况下是拿不到的,子组件需要对外暴露才行

<template>
    <div class="father">
        <h3>父组件</h3>
        <h4>房产:{{ house }}</h4>
        <button @click="changeToy">修改child的玩具</button>
        <Child ref="c1"></Child>
        <Child2></Child2>
    </div>
</template>

<script setup lang="ts" name="Father">
import Child from './Child.vue';
import Child2 from './Child2.vue';
import { ref } from 'vue';
let c1 = ref()

let house = ref(4)
function changeToy() {
    c1.value.toy = '小球'
    console.log(c1.value);
}
</script>
<template>
    <div class="child">
        <h3>子组件</h3>
        <h4>玩具:{{ toy }}</h4>
        <h4>书:{{ book }}</h4>
    </div>
</template>

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

let toy = ref('奥特曼')
let book = ref(3)
// 组件内部数据对外关闭的,别人不能访问,如果想外部访问需要通过defineExpose方法对外暴露
defineExpose({ toy, book })
</script>

<style lang="scss" scoped>
.child {
    width: 80%;
    background-color: sandybrown;
    border: 1px solid rgb(252, 153, 66);
}
</style>

在这里插入图片描述

2. $parent获取父组件实例对象

<Dau></Dau>


<script setup lang="ts">
//$parent:可以在子组件内部获取到父组件的实例
//引入子组件
import Dau from './Daughter.vue'
import { ref } from 'vue'
//父组件钱数
let money = ref(100000000)
//对外暴露
defineExpose({
  money
)}
</script>
<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: any) => {
  console.log($parent)
  money.value += 10000
  $parent.money -= 10000
}
</script>

provide-inject 实现隔辈传输

父组件:用provide传输对应的数据,并提供一个key,后续的子组件在拿数据也是根据此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>

子组件:使用inject和对应的key获取到对应的数据

<template>
  <div class="child">
    <h1>我是子组件1{{ car }}</h1>
    <Child></Child>
  </div>
</template>
 
<script setup lang="ts">
import Child from './GrandChild.vue'
import { inject } from 'vue'
//注入祖先组件提供数据
//需要参数:即为祖先提供数据的key
let car = inject('TOKEN')
</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>

下周总结

项目项目项目,专业课专业课专业课


原文地址:https://blog.csdn.net/2302_80244686/article/details/143664982

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!