vue3(五)(插槽slot,Teleport传送组件,keep-alive缓存组件,依赖注入Provide / Inject)
插槽slot
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
匿名插槽
子组件
<template>
<div>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
</script>
父组件
<template>
<div>
<HelloWorld>
<template v-slot>
<div>HelloWorld</div>
</template>
</HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
</script>
<style>
</style>
具名插槽
具名插槽其实就是给插槽取个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中
子组件
<template>
<div>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
</template>
<script setup lang="ts">
import { reactive } from "vue";
</script>
父组件
<template>
<div>
<HelloWorld>
<template v-slot:header>
<div>1</div>
</template>
<template v-slot>
<div>2</div>
</template>
<template v-slot:footer>
<div>3</div>
</template>
</HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
</script>
<style>
</style>
插槽简写用 #
<template>
<div>
<HelloWorld>
<template #header>
<div>1</div>
</template>
<template #default>
<div>2</div>
</template>
<template #footer>
<div>3</div>
</template>
</HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
</script>
<style>
</style>
作用域插槽
在子组件动态绑定参数 派发给父组件的slot去使用
子组件
<template>
<div>
<slot name="header"></slot>
<div>
<div v-for="item in 10" :key="item">
<slot :data="item"></slot>
</div>
</div>
<slot name="footer"></slot>
</div>
</template>
<script setup lang="ts">
import { reactive } from "vue";
</script>
父组件
<template>
<div>
<HelloWorld>
<template #header>
<div>1</div>
</template>
<template #default="{ data }">
<div>{{ data }}</div>
</template>
<template #footer>
<div>3</div>
</template>
</HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
</script>
<style>
</style>
动态插槽
插槽可以是一个变量名
子组件
<template>
<div>
<slot name="header"></slot>
</div>
</template>
<script setup lang="ts">
import { reactive } from "vue";
</script>
父组件
<template>
<div>
<HelloWorld>
<template #[name]>
<div>
123
</div>
</template>
</HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
import { ref } from "vue";
const name = ref('header')
</script>
<style>
</style>
Teleport传送组件
Teleport Vue 3.0新特性之一。
Teleport 是一种能够将我们的模板渲染至指定DOM节点,不受父级style、v-show等属性影响,但data、prop数据依旧能够共用的技术;类似于 React 的 Portal。
主要解决的问题 因为Teleport节点挂载在其他指定的DOM节点下,完全不受父级style样式影响
使用方法
通过to 属性 插入指定元素位置 to="body" 便可以将Teleport 内容传送到指定位置
<template>
<div>
<Teleport to="body">
<HelloWorld></HelloWorld>
</Teleport>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
import { ref } from "vue";
</script>
<style>
</style>
动态控制teleport
使用disabled 设置为 true则 to属性不生效 false 则生效
<template>
<div>
<Teleport :disabled="false" to='body'>
<HelloWorld></HelloWorld>
</Teleport>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
import { ref } from "vue";
</script>
<style>
</style>
keep-alive缓存组件
有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就需要用到keep-alive组件。
开启keep-alive 生命周期的变化
初次进入时: onMounted> onActivated
退出后触发 deactivated
再次进入:
只会触发 onActivated
事件挂载的方法等,只执行一次的放在 onMounted中;组件每次进去执行的方法放在 onActivated中
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
include 和 exclude
<keep-alive :include="" :exclude="" :max=""></keep-alive>
include 和 exclude 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
max
<keep-alive :max="10"> <component :is="view"></component> </keep-alive>
依赖注入Provide / Inject
Provide / Inject
通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
官网的解释很让人疑惑,那我翻译下这几句话:
provide 可以在祖先组件中指定我们想要提供给后代组件的数据或方法,而在任何后代组件中,我们都可以使用 inject 来接收 provide 提供的数据或方法。 
看一个例子
父组件传递数据
<template>
<div>
<HelloWorld></HelloWorld>
</div>
</template>
<script setup lang="ts">
import HelloWorld from "../components/HelloWorld.vue";
import { provide, ref } from 'vue'
let flag = ref<number>(1)
provide('flag', flag)
</script>
<style>
</style>
子组件接收
<template>
<div style="background-color: green;">
我是子组件
<button @click="change">change falg</button>
<div>{{ flag }}</div>
</div>
</template>
<script setup lang='ts'>
import { inject, Ref, ref } from 'vue'
const flag = inject<Ref<number>>('flag', ref(1))
const change = () => {
flag.value = 2
}
</script>
<style>
</style>
TIPS 你如果传递普通的值 是不具有响应式的 需要通过ref reactive 添加响应式
使用场景
当父组件有很多数据需要分发给其子代组件的时候, 就可以使用provide和inject


浙公网安备 33010602011771号