Vue3:通信组件

news2024/9/22 17:17:44

1.Props

父传子:直接传递需要获取的属性

子传父:需要借助函数,也就是方法,通过传递函数,子接着入参给函数,父调用函数即可获取到参数。

父:

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


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

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

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

子:

<template>
    <div class="child">
        <h3>子组件</h3>
        <h4>玩具:{{ toy }}</h4>
        <h4>父亲给的汽车:{{ car }}</h4>
        <button @click="sendToy(toy)">给父亲玩具</button>
    </div>
</template>
    
    
<script setup lang="ts" name="Child">

import { ref } from 'vue';

let toy = ref('奥特曼')

defineProps(['car', 'sendToy'])
</script>

2.自定义事件

使用@,声明一个自定义事件,并绑定一个函数,传递给子子组件通过接收该自定义事件,

     <!-- 自定义事件 -->
        <Child  @send-toy="saveToy" />

 子接收自定义时间,并绑定点击事件,通过入参,实现数据的传递

let emit = defineEmits(['send-toy'])
    <button @click="emit('send-toy',toy)">传递玩具给父亲</button>

3.mitt(绑定-订阅接收)任意组件消息传递(类似于RabbitMQ)

import mitt from 'mitt'
import { ref } from 'vue'

let emitter = mitt()

let num = ref(0)

// 绑定事件
emitter.on('add', () => {
    console.log('add被调用了', num)
})
// 每隔1秒执行事件
setInterval(() => {
    emitter.emit('add')
}, 1000)

setTimeout(() => {
    // 解绑事件
    emitter.off('add')
}, 5000)

export default emitter

接收数据,需要绑定事件,也就是订阅。避免内存溢出,组件卸载之后,解绑事件

let food = ref('')
emitter.on('send-food', (value: string) => {
    food.value = value
})

onUnmounted(() => {
    emitter.off('send-food')
})

发送数据,需要执行事件

     <button @click="emitter.emit('send-food', food)">分享食物给弟弟</button>

4.v-model,一般用于UI库的底层实现

例如el input 输入框,底层编写了输入框组件,并且通过v-model实现数据的双向绑定

5.$attrs

父组件向子组件传递数据,attrs存储的是被defineProps接收的值,可以通过$attrs获取

<Child :car="car" :sendToy="getToy" @send-toy="saveToy" :a="a" :b="b" :updateA="updateA"/>
defineProps(['car', 'sendToy'])
   <h4>attrs:a:{{ $attrs.a }}</h4>
   <h4>attrs:b:{{ $attrs.b }}</h4>
   <button @click="$attrs.updateA(6)">修改a</button>

6.$refs,$parent

都需要集合defineExpose,将需要传递的数暴露出去

$refs :子传父

 <button @click="addBook($refs)">给孩子买书</button>
 <Child ref="c1" />


let c1 = ref()
function updateA(value: number) {
    a.value += value
}
defineExpose({book})

$parent:父传子

defineExpose({ house })
<button @click="minusHouse($parent)">得到父亲的一套房子</button>



function minusHouse(parent:any){
    console.log(parent)
    parent.house -=1
}

7.provide(提供数据)、inject(接收数据)

let money = ref(100)
provide('moneyContext',{money,updateMoney})
    <h4>父亲的钱:{{ money }}</h4>
    <button @click="updateMoney(6)">花父亲的钱</button>

let { money, updateMoney } = inject('moneyContext', { money: 55, updateMoney: (value: number) => { } })

8.插槽slot

8.1 默认插槽

引入子组件,组间标签内编写内容

在子组件,使用<slot>j进行占位

<template>
    <div class="father">
        <h2>父组件</h2>
        <div class="content">
            <Child title="今日游戏列表">
                <ul>
                    <li v-for=" (item, index) in games" :key="index">{{ item }}</li>
                </ul>
            </Child>
            <Child title="今日美食推荐">
                <img :src="imgUrl">
            </Child>
            <Child title="今日影视推荐">
                <video :src="videoUrl" controls />
            </Child>
        </div>

    </div>


</template>


<script>
export default {
    name: 'Father'
}

</script>
<script setup>
import Child from './Child.vue';
import { ref, reactive } from 'vue';

let games = reactive([
    '王者荣耀',
    '绝地求生',
    '天天酷跑'
])

let imgUrl = ref('http://47.113.201.132:9001/api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL215bGlmZS8yMDI0LzA4LzE2L2NkNjY3YWY2YzAxMzRiNmZhZGZhMTMwZjk4NGQ0MGUxLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPVNVTEdOWTY3RVpFMFoyVVZNVTFUJTJGMjAyNDA4MzAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODMwVDAxNTEzNVomWC1BbXotRXhwaXJlcz00MzE5NiZYLUFtei1TZWN1cml0eS1Ub2tlbj1leUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaFkyTmxjM05MWlhraU9pSlRWVXhIVGxrMk4wVmFSVEJhTWxWV1RWVXhWQ0lzSW1WNGNDSTZNVGN5TlRBeU5UZ3lOQ3dpY0dGeVpXNTBJam9pY205dmRDSjkuOElYdU9CR2w3V2p5QWR5LUpoSVRMQml5dmJTRmhHM3lLNmZpUWE3RS1aaHQzV3o3TkdsMzdGUjlTal90aXdLNk4ySmxtcUhRNmtSQmxtODVzajNUa2cmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnZlcnNpb25JZD1udWxsJlgtQW16LVNpZ25hdHVyZT0xNjE5NmViYzcwZTM2MDkxNDQ4Y2ZmMmMzYTc3ODY4NzZmZTllNDhmYTZkMGQ5Y2JkMmU4NzE2NmM3MDQ4YWQw')

let videoUrl = ref('http://vjs.zencdn.net/v/oceans.mp4')
</script>


<style scoped>
.father {
    background-color: antiquewhite;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 10px;
}

.content {
    display: flex;
    justify-content: space-evenly;
}

img,
video {
    width: 90%;
}
</style>
<template>
    <div class="child">
        <h2>{{ title }}</h2>
        <slot></slot>
    </div>
</template>

<script>
export default {
    name: 'Child'
}
</script>

<script setup>
defineProps(['title'])
</script>

<style scoped>
.child {
    background-color: aquamarine;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 20px;
    width: 200px;
    height: 300px;
}

h2 {
    background-color: yellow;
    text-align: center;

}
</style>

8.2 具名插槽:使用多个插槽,填充不同的内容

数据在父组件,结构也在父组件,填充的位置由子组件定义。

<template>
    <div class="father">
        <h2>父组件</h2>
        <div class="content">

            <Child>
                <template v-slot:s1>
                    <h2>今日游戏列表</h2>
                </template>
                <template v-slot:s2>
                    <ul>
                        <li v-for=" (item, index) in games" :key="index">{{ item }}</li>
                    </ul>
                </template>
            </Child>
            <Child>
                <template v-slot:s1>
                    <h2>今日美食推荐</h2>
                </template>
                <template v-slot:s2>
                    <img :src="imgUrl">
                </template>

            </Child>
            <Child>
                <template #s1>
                    <h2>今日影视推荐</h2>
                </template>
                <template #s2>
                    <video :src="videoUrl" controls />
                </template>
            </Child>
        </div>

    </div>


</template>


<script>
export default {
    name: 'Father'
}

</script>
<script setup>
import Child from './Child.vue';
import { ref, reactive } from 'vue';

let games = reactive([
    '王者荣耀',
    '绝地求生',
    '天天酷跑'
])

let imgUrl = ref('http://47.113.201.132:9001/api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL215bGlmZS8yMDI0LzA4LzE2L2NkNjY3YWY2YzAxMzRiNmZhZGZhMTMwZjk4NGQ0MGUxLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPVNVTEdOWTY3RVpFMFoyVVZNVTFUJTJGMjAyNDA4MzAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODMwVDAxNTEzNVomWC1BbXotRXhwaXJlcz00MzE5NiZYLUFtei1TZWN1cml0eS1Ub2tlbj1leUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaFkyTmxjM05MWlhraU9pSlRWVXhIVGxrMk4wVmFSVEJhTWxWV1RWVXhWQ0lzSW1WNGNDSTZNVGN5TlRBeU5UZ3lOQ3dpY0dGeVpXNTBJam9pY205dmRDSjkuOElYdU9CR2w3V2p5QWR5LUpoSVRMQml5dmJTRmhHM3lLNmZpUWE3RS1aaHQzV3o3TkdsMzdGUjlTal90aXdLNk4ySmxtcUhRNmtSQmxtODVzajNUa2cmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnZlcnNpb25JZD1udWxsJlgtQW16LVNpZ25hdHVyZT0xNjE5NmViYzcwZTM2MDkxNDQ4Y2ZmMmMzYTc3ODY4NzZmZTllNDhmYTZkMGQ5Y2JkMmU4NzE2NmM3MDQ4YWQw')

let videoUrl = ref('http://vjs.zencdn.net/v/oceans.mp4')
</script>


<style scoped>
h2 {
    background-color: yellow;
    text-align: center;

}

.father {
    background-color: antiquewhite;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 10px;
}

.content {
    display: flex;
    justify-content: space-evenly;
}

img,
video {
    width: 90%;
}
</style>
<template>
    <div class="child">
        <slot name="s1">默认内容1</slot>
        <slot name="s2">默认内容2</slot>
    </div>
</template>

<script>
export default {
    name: 'Child'
}
</script>

<script setup>
</script>

<style scoped>
.child {
    background-color: aquamarine;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 20px;
    width: 200px;
    height: 300px;
}
</style>

8.3 作用域插槽

数据在子组件,结构在父组件,需要传递数据给父组件

<template>
    <div class="father">
        <h2>父组件</h2>
        <div class="content">

            <Child1>
                <template v-slot:s1>
                    <h2>今日游戏列表</h2>
                </template>
                <template v-slot="params">
                    <span>{{ params }}</span>
                    <ul>
                        <li v-for="item in params.youxi" :key="item.id">{{ item.name }}</li>
                    </ul>
                </template>
            </Child1>


            <Child1>
                <template v-slot:s1>
                    <h2>今日游戏列表</h2>
                </template>
                <template #default="params">
                    <span>{{ params }}</span>
                    <ol>
                        <li v-for="item in params.youxi" :key="item.id">{{ item.name }}</li>
                    </ol>
                </template>
            </Child1>

          
        </div>

    </div>


</template>


<script>
export default {
    name: 'Father'
}

</script>
<script setup>
import { ref, reactive } from 'vue';
import Child1 from './Child1.vue';

let games = reactive([
    '王者荣耀',
    '绝地求生',
    '天天酷跑'
])

let imgUrl = ref('http://47.113.201.132:9001/api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL215bGlmZS8yMDI0LzA4LzE2L2NkNjY3YWY2YzAxMzRiNmZhZGZhMTMwZjk4NGQ0MGUxLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPVNVTEdOWTY3RVpFMFoyVVZNVTFUJTJGMjAyNDA4MzAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODMwVDAxNTEzNVomWC1BbXotRXhwaXJlcz00MzE5NiZYLUFtei1TZWN1cml0eS1Ub2tlbj1leUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaFkyTmxjM05MWlhraU9pSlRWVXhIVGxrMk4wVmFSVEJhTWxWV1RWVXhWQ0lzSW1WNGNDSTZNVGN5TlRBeU5UZ3lOQ3dpY0dGeVpXNTBJam9pY205dmRDSjkuOElYdU9CR2w3V2p5QWR5LUpoSVRMQml5dmJTRmhHM3lLNmZpUWE3RS1aaHQzV3o3TkdsMzdGUjlTal90aXdLNk4ySmxtcUhRNmtSQmxtODVzajNUa2cmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnZlcnNpb25JZD1udWxsJlgtQW16LVNpZ25hdHVyZT0xNjE5NmViYzcwZTM2MDkxNDQ4Y2ZmMmMzYTc3ODY4NzZmZTllNDhmYTZkMGQ5Y2JkMmU4NzE2NmM3MDQ4YWQw')

let videoUrl = ref('http://vjs.zencdn.net/v/oceans.mp4')
</script>


<style scoped>
h2 {
    background-color: yellow;
    text-align: center;

}

.father {
    background-color: antiquewhite;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 10px;
}

.content {
    display: flex;
    justify-content: space-evenly;
}

img,
video {
    width: 90%;
}
</style>
<template>
    <div class="child1">
        <slot name="s1"></slot>
        <slot :youxi="games"></slot>
    </div>

</template>


<script lang="ts" setup name="Child1">
import { reactive } from 'vue';

let games = reactive([
    {
        id: 111,
        name: "王者荣耀"
    },
    {
        id: 2222,
        name: "QQ飞车"
    },
    {
        id: 333,
        name: "斗地主"
    }
])
</script>


<style scoped>
.child1 {
    background-color: aquamarine;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 20px;
    width: 200px;
    height: 300px;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2090938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

卡西莫多的诗文集2022-2024.8月定稿

通过网盘分享的文件&#xff1a;卡西莫多的诗文集2022-2024.8月30-A5.pdf 链接: https://pan.baidu.com/s/1_BrcKvUthFLlty8dWNZxjQ?pwdutwd 提取码: utwd 自从解锁了一项新技能后&#xff0c;从藏内容诗开始&#xff0c;自己积攒到现在不知不觉也积累了一些诗&#xff0c;看…

python模块06 mock-1基础用法

0 为什么要使用mock&#xff1f; 测试接口时&#xff0c;需要有对应的接口可以测试才行&#xff0c;否则要等后端开发完&#xff0c;才能进行&#xff0c; mock模块可以模拟后端接口返回数据&#xff0c;提前根据接口文档准备好后端的静态数据 1mock基础用法 下载&#xff…

M1 card crack

判断卡片类型 这张卡就是本次实现的对象 &#xff0c;一张废弃的校园卡&#xff0c;以下所有操作都以此卡展开 我们使用flipper的NFC功能扫描该卡片。我们直接read 我们得出最终结果该卡是M1 1K卡&#xff0c;也就是S50卡 。 Mifare 1卡是属于非接触式逻辑加密卡。MIFARE M…

锂电池基本知识与设计

目录 摘要 充电过程 18650规格书分享 摘要 应用&#xff1a;笔记本电脑、智能手机等设备。 优点&#xff1a;较高能量密度和较长使用寿命&#xff0c;放电率低&#xff0c;可进一步延长充电间隔时间。 缺点&#xff1a;过度充电或者放电会产生不可逆的损伤&#xff0c;性…

让PDF格式为LLM应用做好准备:探索Marker开源工具

在如今的大数据时代&#xff0c;高质量的数据可谓是LLM&#xff08;大语言模型&#xff09;应用成功与否的关键因素。然而&#xff0c;大多数文本数据通常以PDF格式存在。这不仅适用于企业文档&#xff0c;也包括个人文件。然而&#xff0c;对于LLM而言&#xff0c;处理PDF文件…

全局页面数据渲染--SAAS本地化及未来之窗行业应用跨平台架构

一、代码 /* 未来之窗通用数据渲染// 定义了一个名为"未来之窗_人工智能_前端口_数据渲染到界面"的函数 function 未来之窗_人工智能_前端口_数据渲染到界面(obj, 前置参数) {// 开启一个控制台分组&#xff0c;用于组织相关的输出信息console.group("未来之窗…

多参数遥测终端科技守护水电站生态流量下泄

随着我国水电事业的蓬勃发展&#xff0c;水电站在推动地方经济快速增长、缓解能源压力方面发挥了不可替代的作用。然而带来的生态环境问题日益凸显&#xff0c;因水电站下泄流量不足造成部分河段减水、脱水甚至干涸&#xff0c;影响了河流的正常生态功能和居民的生产、生活。因…

【 html+css 绚丽Loading 】 000027 旋风破云扇

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

《机器学习》数据分析之关键词提取、TF-IDF、项目实现 <下>

目录 一、内容回顾 1、核心算法 2、算法公式 3、拆分文本 二、再次操作 1、取出每一卷的地址和内容 得到下列结果&#xff1a;&#xff08;此为DF类型&#xff09; 2、对每一篇文章进行分词 3、计算TF-IDF值 得到以下数据&#xff1a; 三、总结 1、关键词提取 1&a…

【Spring MVC】MVC设计模式的Java Web框架

Spring MVC框架 MVC框架简介&#xff1a;MVC三层架构MVC流行框架MVC框架好处&#xff1a; Spring MVC框架组件分析 处理器开发1. 定义处理器2. 处理请求3. 处理请求参数4. 返回视图或数据5. 异常处理 MVC框架简介&#xff1a; 谈及Spring MVC框架之前&#xff0c;我们先了解一…

C语言基础(二十九)

1、快速排序&#xff1a; #include "date.h" #include <stdio.h> #include <stdlib.h> #include <time.h> // 函数声明 void quickSort(int *arr, int low, int high); void swap(int *xp, int *yp); void printArray(int *arr, int s…

CSRF漏洞的预防

目录 CSRF漏洞预防措施 深入研究 CSRF Token的工作原理是什么&#xff1f; 为什么仅依靠Referer头字段来防范CSRF攻击不是完全可靠&#xff1f; SameSite cookie属性如何防止CSRF攻击&#xff1f; SameSite Cookie属性的作用 如何通过SameSite属性防止CSRF攻击 导图 CS…

JavaWeb JavaScript ⑧ DOM编程

在光芒万丈之前&#xff0c;我们都要欣然接受眼下的难堪和不易&#xff0c;接受一个人的孤独和无助&#xff0c;认真做好眼前的每一件事&#xff0c;你想要的都会有 —— 24.8.29 一、什么是DOM编程 简单来说&#xff1a;DOM(Document obiect Model)编程就是使用document对象的…

Python 如何进行密码学操作(cryptography模块)

Python 的密码学操作可以通过 cryptography 模块来实现&#xff0c;这个模块是一个功能强大的库&#xff0c;它提供了现代密码学的基本工具&#xff0c;包括加密、解密、密钥生成、签名等操作。cryptography 模块易于使用&#xff0c;并且安全性高&#xff0c;适合在各种场景下…

【软件测试】8. 测试分类

目录 1. 为什么要对软件测试进行分类&#xff1f; 2.按照测试目标分类 2.1 界面测试 2.2 功能测试 2.3 性能测试 2.4 可靠性测试 2.5 安全性测试 2.6 易用性测试 3.按照执行方式分类 3.1 静态测试 3.2 动态测试 4. 按照测试方法 4.1 白盒测试 4.2 黑盒测试 4.3灰…

【WiFi协议的发展学习1】

WiFi协议的发展 WiFi协议的发展2. WiFi协议发展3. WiFi协议发展小结3.1. 发展归纳3.2. 未来展望4. WiFi产品的特点/功能WiFi协议的发展 自20世纪90年代以来, WiFi技术得到了迅猛发展,已成为人们日常生活、工作和学习中不可或缺的组成部分。WiFi协议的发展不仅推动了无线通信…

TL-Tomcat 整体架构和处理请求流程解析

我们写一个servlet后&#xff0c;在web.xml里配上我们的路径。然后把项目打包成war包放入webapps目录下 然后这样就返回了 这个war包里面的东西和这个文件夹其实是一样的&#xff1a; 那么最终我们把war包删掉 还有原来文件夹下其他的东西 只剩下这么个.class文件 其实这…

TikTok流量推送逻辑与IP的关系

在探讨TikTok流量推送逻辑时&#xff0c;很多用户都好奇这一机制是否与用户的IP地址紧密相关。TikTok作为全球知名的短视频社交平台&#xff0c;其流量推送算法无疑是平台成功的关键因素之一。那么&#xff0c;TikTok的流量推送逻辑究竟是如何运作的&#xff1f;它与IP地址之间…

C语言 | Leetcode C语言题解之第385题迷你语法分析器

题目&#xff1a; 题解&#xff1a; struct NestedInteger* helper(const char * s, int * index){if (s[*index] [) {(*index);struct NestedInteger * ni NestedIntegerInit();while (s[*index] ! ]) {NestedIntegerAdd(ni, helper(s, index));if (s[*index] ,) {(*index…

使用InternLM实现谁是卧底游戏

环境 # 创建虚拟环境 conda create -n spy python3.10 -y conda activate spy pip install streamlit1.37.0 openai1.37.1 git clone https://github.com/sci-m-wang/Spy-Game.git cd Spy-Game 修改脚本who_is_the_spy.py中的client 部分 if "client" not in …