Fork me on GitHub

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

  

 

 


————————————————
版权声明:本文为CSDN博主「小满zs」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq1195566313/article/details/122904105

 

posted @ 2022-11-03 10:48  小白不白10  阅读(453)  评论(0编辑  收藏  举报