vue动态组件和插槽

让多个组件使用同一个挂载点,并动态切换,这就是动态组件

1. 实现

动态组件借助component标签和它的is属性实现:

<div id="app">
    <!-- 原来的写法 -->
    <test></test>

    <!-- 改为动态组件 -->
    <component is="test"></component>
</div>

2. 组件缓存

把组件的引入改为动态引入后,每次加载组件都会重新渲染,出于性能考虑,为避免多次重复渲染降低性能。Vue 提供了keep-alive标签用于组件缓存,切换组件后,原来的组件不会被清除,而是维持当前的状态。

官网解释:<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。 当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。 在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 <keep-alive> 树内的所有嵌套组件中触发。 主要用于保留组件状态或避免重新渲染。

示例:

<div id="app">
    <keep-alive>
        <!-- 被包裹的动态组件可以被缓存 -->
        <component :is="view"></component>
    </keep-alive>
</div>

应用场景

如果未使用keep-alive组件,则在页面回退时仍然会重新渲染页面,触发created钩子,使用体验不好。 在以下场景中使用keep-alive组件会显著提高用户体验,菜单存在多级关系,多见于列表页+详情页的场景如:

  • 商品列表页点击商品跳转到商品详情,返回后仍显示原有信息
  • 订单列表跳转到订单详情,返回,等等场景。

2.1 keep-alive的生命周期

  • 初次进入时:created > mounted > activated;退出后触发 deactivated
  • 再次进入:会触发 activated;

事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中

1. 简介

Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。

Slot 通俗的理解就是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置)
并且可以作为承载分发内容的出口 .

插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到模板template指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制。

插槽含义:引入子组件后,在插入子组件元素中添加信息或者标签,使得子组件的指定位置插入信息或者标签

插槽有三种:默认插槽、具名插槽、作用域插槽.

插槽,其实就相当于占位符。它在组件中给你的HTML模板占了一个位置,让你来传入一些东西。插槽又分为匿名插槽、具名插槽以及作用域插槽。

没有插槽的情况下在组件标签内些一些内容是不起任何作用的,当我在组件中声明了slot元素后,在组件元素内写的内容就会跑到它这里了!

插槽是父组件与子组件新的通讯的方式,可以将父组件里面的内容显示到子组件中(包括标签)

2. 插槽使用

创建 product.vue 组件,然后引入 productDetail.vue 组件

<template>
    <div>
        <h3>product.vue组件</h3>
        <!-- 标签内的内容 会出现在 子组件写的插槽位置 -->
        <productDetail>hello productDetail </productDetail>
    </div>
</template>
<script>
    import productDetail from "./produceDetail"
</script>

创建 productDetail.vue 组件

<template>
    <div>
        <h3>productDetail.vue组件</h3>
        <!-- slot 标签就是插槽标签,它会被替换为 父组件使用子组件标签时写在标签内的内容 如:hello productDetail -->
        <slot></slot>
    </div>
</template>

当组件渲染的时候,<slot></slot>会被替换为hello productDetail

插槽内也可以包含任何模板代码,包括HTML

<h3>product.vue组件</h3>
<productDetail>
    <!-- 添加标签 -->
    <h3>hello productDetail</h3>
</productDetail>

如果<productDetail>中没有包含一个<slot>元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。

在插槽中使用数据

插槽跟模板其他地方一样都可以访问相同的实例属性而不能访问<productDetail>的实例属性

<template >
    <div>
        <h3>product.vue组件</h3>
        <productDetail>
            <!-- 可以访问到 product 的数据 -->
            <h3>hello productDetail--{{count}}</h3>
        </productDetail>
    </div>
</template>
<script>
    import productDetail from "./ProductDetail"
    export default {
        data() {
            return {
                count:100
            }
        },
        components:{
            productDetail
        }
    }
</script>

规则:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

3. 默认插槽 (匿名)

有时候我们需要给插槽设置一个具体的默认内容,当别的组件没有给你内容的时候,那么默认的内容就会被渲染

<template>
  <div>
    <h3>productDetail.vue组件</h3>
    <!-- 在slot插槽里设置默认内容 hello -->
    <slot>hello</slot>
  </div>
</template>

在 product 组件中直接使用,默认内容 hello 将会被渲染。

4. 具名插槽

有时候我们一个组件里需要多个插槽,对于这样的情况,slot标签通过name属性区分不同的插槽。

默认插槽的name值为default。父组件通过在template标签上写v-slot:name属性来给对应的插槽插入内容。

注意:v-slot属性只能添加在template标签上。

<template>
  <div>
    <h3>productDetail.vue组件</h3>
    <!-- 插槽默认名字为 default -->
    <slot></slot>

    <!-- 给插槽起名字 -->
    <slot name="title"></slot>
    <slot name="price"></slot>
  </div>
</template>

product.vue 组件

<template >
    <div>
        <h3>product.vue组件</h3>
        <productDetail>
            <!-- 通过 template 标签添加 v-slot:插槽名 给对应的插槽赋值 -->
            <template v-slot:title>
                <h3>OPPO Reno6 Pro+ 12+256GB</h3>
            </template>
            <template v-slot:price>
                <h3>¥ 3499.00</h3>
           </template>
        </productDetail>
    </div>
</template>

缩写:

v-onv-bind一样,v-slot也有缩写,可以将v-slot: 替换为字符 #

<productDetail>
  <template #title>
     <h3>OPPO Reno6 Pro+ 12+256GB</h3>
   </template>
   <template #price>
     <h3>¥ 3499.00</h3>
   </template>
</productDetail>

5. 作用域插槽

如果我们想要在插槽内使用子组件的数据,可以使用作用域插槽。

  1. 在子组件中将父组件使用的数据绑到 <slot> 上
  2. 在父组件中用v-slot设置一个值来接收子组件传递的属性
<template>
  <div>
    <h3>productDetail.vue组件</h3>
    <!-- 在子组件中添加对应的属性,将值传递给插槽 -->
    <slot name="student" :student="people"></slot>
    <slot name="goods" :goods="goodsList"></slot>
  </div>
</template>
<script setup>
export default {
  data(){
    return {
      id:'100026761908',
       people:{
        name:'lucky',
        age:12
      },
      goodsList:[
        {
          id:1102,
          name:'戴尔(DELL)游匣G15 15.6英寸',
          price:'¥ 5199.00'
        },
        {
          id:'1106',
          name:'美的(Midea)S8+自动集尘扫拖机器人',
          price:'¥ 2499.00'
        },
        {
          id:'11056',
          name:'Apple Watch SE',
          price:'¥ 2119.00'
        }
      ]
    }
  }
}
</script>

product.vue 组件:

<productDetail>
    <!-- 通过命名组件="变量" 接收子组件传递的值 -->
    <template #student="studentDetail">
        <!-- 变量的值是一个对象,属性由子组件传递的属性组成 -->
        {{studentDetail}}
        <p>
            当前学生的名字是:{{studentDetail.student.name}},
            当前学生的姓名是:{{studentDetail.student.age}}
        </p>
    </template>
</productDetail>

5.1 解构传值

我们可以使用解构的形式获取到子组件传递给插槽的值:

product.vue 组件:

<productDetail>
    <!-- 解构获取 -->
    <template #student={student}>
        {{student}}
        <p>
            当前学生的名字是:{{student.name}},
            当前学生的姓名是:{{student.age}}
        </p>
    </template>
</productDetail>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值