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

《Vue3学习手记7》

组件通信(续)

$attrs

组件通信:$attrs 适用于祖传孙孙传祖 (需要通过中间组件)
传递给后代的数据,但未被接收,都保存在attrs中

1.祖传孙

父组件:

<template><div class="father"><h3>父组件</h3><h3>a:{{ a }}</h3><h3>b:{{ b }}</h3><h3>c:{{ c }}</h3><Child :a="a" :b="b" :c="c"/>  <!-- 1.1.传递给儿子 --></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref} from 'vue'let a=ref(1)let b=ref(2)let c=ref(3)// 2.使用attrs实现孙传祖let gift=ref("")// 2.1 getGift函数function getGift(value:string){gift.value=value}// 使用mitt实现孙传祖// let gift=ref("")// emitter.on("getGift",(value:string)=>{// 	gift.value=value// })
</script>

子组件:

<template><div class="child"><h3>子组件</h3><GrandChild v-bind="$attrs"/>  <!-- 1.2.儿子将父亲传递过来但未被接收的数据传给孙子 --></div>
</template><script setup lang="ts" name="Child">import GrandChild from './GrandChild.vue'
</script>

孙组件:

<template><div class="grand-child"><h3>孙组件</h3><h3>a:{{ a }}</h3><h3>b:{{ b }}</h3><h3>c:{{ c }}</h3></div>
</template><script setup lang="ts" name="GrandChild">
import {ref} from "vue"
const gift=ref("飞机")// 1.3 孙子接收数据defineProps(["a","b","c"])  //1.4 注意接收的内容
</script>

2.孙传祖

父组件:

<template><div class="father"><h3>父组件</h3><h3>a:{{ a }}</h3><h3>b:{{ b }}</h3><h3>c:{{ c }}</h3><Child :a="a" :b="b" :c="c" :getGift="getGift"/> <-- 2.2 将getGift函数传递过去--><hr><h2>得到孙子给的礼物:{{ gift }}</h2></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref} from 'vue'let a=ref(1)let b=ref(2)let c=ref(3)// 2.使用attrs实现孙传祖let gift=ref("")// 2.1 getGift函数function getGift(value:string){gift.value=value}
</script>

子组件:

<template><div class="child"><h3>子组件</h3><GrandChild v-bind="$attrs"/>  <!-- 1.2.儿子将父亲传递过来但未被接收的数据传给孙子 --></div>
</template>

孙组件:

<template><div class="grand-child"><h3>孙组件</h3><h3>a:{{ a }}</h3><h3>b:{{ b }}</h3><h3>c:{{ c }}</h3><hr><h4>礼物:{{gift}}</h4><button @click="getGift(gift)">点我将礼物给爷爷</button></div>
</template><script setup lang="ts" name="GrandChild">
import {ref} from "vue"
const gift=ref("飞机")// 1.3.孙子接收数据defineProps(["a","b","c","getGift"])  //1.4注意接收的内容
// 2.3使用attrs实现孙传祖--接收传递过来的函数getGift
</script>

$refs和 $parent

先使用ref进行通信:
父组件:

<template><!-- 组件通信:$refs父传子和$parents子传父 --><!-- 知识点1:ref --><div class="father"><h3>父组件</h3><h2>房子:{{ house }}</h2><h2>财产:{{ money }}</h2><button @click="sendMoney">点击修改儿子1玩具为奥特曼</button><Child1 ref="ch1"/><Child2 ref="ch2"/></div>
</template><script setup lang="ts" name="Father">import Child1 from './Child1.vue'import Child2 from './Child2.vue'import { ref,reactive } from "vue";const house=ref(3)const money=ref(300)// 1.数据const ch1=ref()const ch2=ref()// 2.方法:function sendMoney(){ch1.value.toy="奥特曼"} 
</script>

子组件:

<template><div class="child1"><h3>子组件1</h3><h2>书籍:{{ book }}</h2><h2>玩具:{{toy}}</h2></div>
</template><script setup lang="ts" name="Child1">import { ref } from "vue";const book=ref(4)const toy=ref("乐高")// 3.defineExpose({toy})   //注意!里面是{},不是[]
</script>

$refs 父传子

父组件:

<template><!-- 组件通信:$refs父传子和$parents子传父 --><!-- 知识点1:ref --><div class="father"><h3>父组件</h3><h2>房子:{{ house }}</h2><h2>财产:{{ money }}</h2><button @click="getAll($refs)">获取所有子组件的实例对象</button>  <!-- 获取到所有打了ref标识的组件的实例对象 --><Child1 ref="ch1"/><Child2 ref="ch2"/></div>
</template><script setup lang="ts" name="Father">import Child1 from './Child1.vue'import Child2 from './Child2.vue'import { ref,reactive } from "vue";const house=ref(3)const money=ref(300)//***********************************************************************************
// 知识点二:当有很多子组件都需要修改,那就要写很多代码,可以使用$refs获得所有组件实例对象// $refsfunction getAll(refs:object){// console.log(refs)// 将child1和2的书籍增加两本// 遍历  (遍历数组用index索引值,遍历对象用key)for (let key in refs){// console.log(key)   //输出ch1和ch2// console.log(refs[key])refs[key].book+=2}}
</script>

子组件:

//子组件1:
defineExpose({toy,book})   
//子组件2:
defineExpose({book}) 

$parent 子传父

子组件:

<template>
<!-- 知识点三:子传父$parent --><button @click="reduceMoney($parent)">点我父亲资产减10</button>
</template><script setup lang="ts" name="Child1">import { ref } from "vue";const book=ref(4)const toy=ref("乐高")// ***********************************3.1 function reduceMoney(parent:any){  //"parent"自己定义// console.log(parent)    //得到的就是父组件defineExpose的数据parent.money-=10}
</script>

父组件:

// 3.2 defineExpose({money})

provide和inject

组件通信:provide和inject祖孙通信。
和attrs区别在于:不用使用中间组件而attrs需要使用中间组件

祖组件:

祖——孙

<template>组件通信:provide和inject祖孙通信。和attrs区别在于:不用使用中间组件而attrs需要使用中间组件 <div class="father"><h3>父组件</h3><h2>房子:{{ house }}</h2><h2>财产:{{ money }}</h2><Child/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref,reactive,provide,inject} from 'vue'const house=ref(3)const money=ref(300)// 1.2 爷爷传递数据给孙子provide("money",money)  //第一个money可自定义
</script>

孙组件:

<template><div class="grand-child"><h3>我是孙组件</h3><h2>书籍:{{ book }}</h2><h2>玩具:{{toy}}</h2><h2>得到爷爷的money:{{ money }}</h2></div>
</template><script setup lang="ts" name="GrandChild">import {ref} from "vue"import {provide,inject} from "vue"const book=ref(4)const toy=ref("乐高")// *****************************************************// 知识点一:祖-孙,实现爷爷向孙子通信(传递数据)// 1.1 得到爷爷传过来的数据let money=inject("money",0)//第二个参数是默认值
</script>

孙——祖
祖组件:

 // 2.1定义一个函数function changeMoney(value:number){money.value-=value}// 2.2提供changeMoney函数provide("moneyText",{money,changeMoney}) //提供多个内容用对象形式

孙组件:

 <button @click="changeMoney(2)">点我修改爷爷的money</button>// 知识点二:孙-祖,实现孙子向爷爷通信(传递数据)// 2.3注入let {money,changeMoney}=inject("moneyText",0)

pinia

可以参考前边对pinia的理解

slot插槽

组件通信:slot-父组件向子组件传递模板内容

默认插槽

数据在父组件
父组件:

<template><div class="father"><Category title="今日游戏推荐"><ul><li v-for="(g,id) in games" :key="id">{{ g.name }}</li></ul></Category><Category title="今日美食推荐"><img :src="img" alt=""></Category><Category title="今日视频推荐"><video :src="video"></video></Category></div>
</template><script setup lang="ts" name="Father">
import Category from './Category.vue';
import {ref,reactive} from 'vue'
let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])const img=ref("https://z1.ax1x.com/2023/11/19/piNxLo4.jpg")const video=ref("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
</script>

子组件:

<template><div class="game"><h2>{{title}}</h2><slot>如果没有内容展示就显示默认内容</slot><!-- 等同于: --><!-- <slot name="default"></slot> --></div>
</template><script setup lang="ts" name="Game">
defineProps(["title"])
</script>

具名插槽

数据在父组件
父组件:
实现h2标题在内容下——一般用于内容展示和模板中的顺序不一样,使用template标签

<template><div class="father"><Category><template v-slot:two>   <!-- 注意!这里不是= --><h2>今日游戏推荐</h2></template><template v-slot:one><ul><li v-for="(g,id) in games" :key="id">{{ g.name }}</li></ul></template></Category><Category><template #two>   <!-- 简写 --><h2>今日美食推荐</h2></template><template #one>   <img :src="img" alt=""></template></Category><Category><template v-slot:two>   <h2>今日视频推荐</h2></template><template v-slot:one>   <video :src="video"></video></template></Category></div>
</template><script setup lang="ts" name="Father">
import Category from './Category.vue';
import {ref,reactive} from 'vue'
let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])const img=ref("https://z1.ax1x.com/2023/11/19/piNxLo4.jpg")const video=ref('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')
</script>

子组件:

<template><div class="game"><h2>{{title}}</h2><slot name="one">如果没有内容展示就显示默认内容</slot><slot name="two"></slot></div>
</template><script setup lang="ts">
defineProps(["title"])</script>

作用域插槽

父组件:
数据在子组件

<template><!-- 作用域插槽 --><div class="father"><Category><template v-slot:two>   <!-- 注意!这里不是= --><h2>今日游戏推荐</h2></template><template v-slot:one="params"><ul><li v-for="(g,id) in params.games" :key="id">{{ g.name }}</li></ul></template></Category><Category><template #two>   <!-- 简写 --><h2>今日美食推荐</h2></template><template #one="params">   <img :src="params.image" alt=""></template></Category><Category><template v-slot:two>   <h2>今日视频推荐</h2></template><template v-slot:one="params">   <video :src="params.video"></video></template></Category></div>
</template><script setup lang="ts" name="Father">
import Category from './Category.vue';
</script>

子组件:

<template><div class="game"><h2>{{title}}</h2><slot name="one" :games="games" :image="img" :video="video">如果没有内容展示就显示默认内容</slot><slot name="two"></slot></div>
</template><script setup lang="ts">
defineProps(["title"])
import {ref,reactive} from 'vue'
let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])const img=ref("https://z1.ax1x.com/2023/11/19/piNxLo4.jpg")const video=ref('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')
</script>

相关文章:

  • 3D Gaussian Splatting部分原理介绍和CUDA代码解读
  • grafana/loki 设置日志保留时间
  • C++的vector中emplace_back() 与 push_back() 的区别
  • 高防 CDN 的防护功能有哪些?从基础防护到智能防御的全面解析
  • redis高级进阶
  • 记录 Flink jdbc、mysql-cdc 连接 mysql8 碰到的适配问题
  • Leetcode刷题记录22——滑动窗口最大值
  • AI Agent Protocols:现状、挑战与未来展望
  • 耐高低温抗金属RFID标签种类和应用场景
  • 【全国产化】基于飞腾 FT2000+/64 核的服务器主板设计与实践
  • LVGL -窗口操作
  • 【MCP Node.js SDK 全栈进阶指南】高级篇(3):MCP 安全体系建设
  • Unity-Shader详解-其三
  • 前端防护利器:disable-devtool 使用指南 - 保护你的Web应用安全
  • 本地知识库工具FASTGPT的安装与搭建
  • Java中final关键字的作用?
  • 信息学奥赛一本通 1454:山峰和山谷
  • 优化PCB Via Stub系列(1):一次学会利用层叠设计降低Via Stub损耗
  • MySQL数据库全面详解:从基础到高级应用
  • ref 和$refs
  • 哈莉·贝瑞、洪常秀等出任戛纳主竞赛单元评委
  • 解放日报头版聚焦“人民城市”:共建共享展新卷
  • “五一”假期倒计时,节前错峰出游机票降价四成
  • 诗词文赋俱当歌,听一听古诗词中的音乐性
  • 李强主持召开国务院常务会议
  • 李在明当选韩国共同民主党总统候选人