vue3通信大全(一)------ 组件通信与provide - 掘金 (juejin.cn)
vue3通信大全(二)------ 路由传参与 teleport - 掘金 (juejin.cn)
vue3通信大全(三)------ 全局状态管理库pinia,vuex - 掘金 (juejin.cn)
前言
前三篇vue3通信文章已经讲了我们常见的组件通信方式,有了他们在组件间传递信息也是游刃有余了。本文将详细介绍最后的组件通信方式,Slot
与KeepAlive
。
Slot 插槽
slot槽提供了一种灵活的方式来组织和重用组件结构,同时也支持条件渲染和动态内容。它的大概的工作原理如下,就是在组件标签内部,放入父组件数据,用来替代子组件需要接受父组件的渲染数据
基础使用
slot基础使用在父组件中非常简单,只需要在组件的自闭合标签内放入传递的信息即可,而在子组件中放置<slot />
的位置将被父组件传递过来的数据代替。
父组件:
xml
<template>
<h1 style="color: brown;">父组件</h1>
<button @click="change">change</button>
<Demo4>
{{ msg }}
</Demo4>
</template>
<script setup>
import Demo4 from "./components/demo4/child.vue";
import {ref}from 'vue'
const msg=ref('父组件初始信息')
const change=()=>{
msg.value='父组件改变后的信息'
}
</script>
子组件:
xml
<template>
<div>
<h2>子组件</h2>
<slot />
</div>
</template>
这里在实验中我们顺带检测了一下父组件让子组件展示的数据是不是跟随着父组件的数据改变而实时更新的,可以看到当父组件的数据发生改变时,子组件展示的数据也发生了改变。
具名插槽
具名插槽是 Vue 中一个非常有用的特性,它允许我们在一个组件的不同位置定义多个插槽,并给这些插槽命名。这使得你可以更精确地控制子组件内部的内容布局。具名插槽允许父组件向子组件的不同位置插入内容。这可以通过在子组件模板中定义具名的 <slot>
元素来实现,并通过 name
属性指定插槽的名称。
父组件:
xml
<template>
<h1>这是app文件</h1>
<Demo4 class="role-select-background1" @click="router.push('/donor')">
<template #title> 这是使用 # </template>
<template #desc>
具名slot 的使用
</template>
</Demo4>
<Demo4 class="role-select-background2" @click="router.push('/donor')">
<template v-slot:title> 这是使用 v-slot </template>
<template v-slot:desc>
具名slot 的使用
</template>
</Demo4>
</template>
子组件:
ini
<template>
<div class="role-select">
<div class="title">
<slot name="title"/>
</div>
<div class="desc">
<slot name="desc" />
</div>
</div>
</template>
这里我们展示了两种常见的具名插槽的用法,当我们使用具名插槽时,<template>
内可以使用v-slot:name
或者#name
来命名插槽。如果父组件没有为某个具名插槽提供内容,那么默认内容(如果有的话)将会被显示。
本地浏览器缓存
使用浏览器的本地存储(如 localStorage
或 sessionStorage
)来进行跨组件或跨页面的数据共享。这在 Vue.js 应用中是一种常见的做法,尤其是在需要持久化数据或在不同组件之间共享数据时。
浏览器提供了两种主要的本地存储机制:
localStorage
: 数据会永久保存,除非用户手动清除或者代码中明确清除。sessionStorage
: 数据仅在当前浏览器会话期间可用,当浏览器窗口关闭时数据会被清除。
父组件:
xml
<template>
<div>
父组件:
</div>
<button @click="updata">上传数据到Storage</button>
<Child />
</template>
<script setup>
import Child from './components/demo4/child.vue';
import { ref } from 'vue';
const data1=ref('父组件的数据localStorageData')
const data2=ref('父组件的数据sessionStorageData')
const updata=()=>{
localStorage.setItem('localApp',data1.value)
sessionStorage.setItem('sessionApp', data2.value);
}
</script>
子组件:
xml
<template>
<div>
子组件
</div>
<button @click="getData">获取local到数据</button>
<h2>{{ data1 }}</h2>
<h2>{{ data2 }}</h2>
</template>
<script setup>
import { ref } from 'vue';
const data1=ref('')
const data2=ref('')
const getData = ()=>{
data1.value=localStorage.getItem('localApp')
data2.value=sessionStorage.getItem('sessionApp')
}
</script>
这里我们同时使用localStorage.setItem
和sessionStorage.setItem
来将值上传到浏览器存储中,再让其他组件通过localStorage.getItem
和sessionStorage.getItem
获取到浏览器存储中的值,从而实现组件间的通信。其实还有cookie等存贮,由于比较难,这里我们不多叙述。想了解的童鞋可以看: 深入解析Cookie机制:从操作实践到安全属性详解 - 掘金 (juejin.cn)
window对象全局挂载
将数据挂载在全局对象身上这个操作不是在vue中常见,但是也是可以实现组件通信的,因为原生JavaScript中就有能够访问window对象的功能,因此我们在vue中当然也是可以访问到window对象的,并且由于window是全局对象,挂载在它身上的实例是可以被所有组件访问。
但是这种方法是绝不被vue推荐的,因为他不会在遵循单向数据流原则,并且对于组件暴露出来给某个组件的数据,是丝毫没有私密性的可言,全部的组件都能够访问到该数据。
子组件:
xml
<template>
<div>
子组件数据:{{ data }}
</div>
</template>
<script setup>
import { ref } from 'vue';
const data=ref('子组件的数据是100')
window.ChildData=data;
</script>
父组件:
xml
<template>
<div>
父组件:
</div>
<button @click="updata">获取子组件的数据</button>
<h1>{{ data }}</h1>
<Child />
</template>
<script setup>
import Child from './components/demo4/child.vue';
import { ref } from 'vue';
const data=ref('')
const updata=()=>{
data.value=window.ChildData
}
</script>
通过将数据和方法挂载到 window
对象上,虽然可以轻松地在整个 Vue.js 应用中访问它们。但是单项数据流原则和组件数据的私密性更应该是我们在开发中应该关注的重点。 而且window上的属性全局变量容易引起命名冲突,尤其是当项目中引入了多个第三方库时,这些库也可能使用相同的变量名。随着项目规模的增长,维护全局挂载的数据会变得越来越困难,因为它缺乏结构化管理。