Vue动态组件、组件缓存、组件激活和非激活、组件插槽、组件name

一、动态组件

如何切换2个组件 互斥的显示或者隐藏呢 除了v-if

什么是动态组件?

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

完成一个注册功能页面, 2个按钮切换, 一个填写注册信息, 一个填写用户简介信息

  1. 准备变量来承载要显示的"组件名"
  2. 设置挂载点, 使用is属性来设置要显示哪个组件
<template>
  <div>
      <button @click="comName = 'UserName'">账号密码填写</button>
      <button @click="comName = 'UserInfo'">个人信息填写</button>

      <p>下面显示注册组件-动态切换:</p>
      <div style="border: 1px solid red;">
          <component :is="comName"></component>
      </div>
  </div>
</template>

<script>
// 目标: 动态组件 - 切换组件显示
// 场景: 同一个挂载点要切换 不同组件 显示
// 1. 创建要被切换的组件 - 标签+样式
// 2. 引入到要展示的vue文件内, 注册
// 3. 变量-承载要显示的组件名
// 4. 设置挂载点<component :is="变量"></component>
// 5. 点击按钮-切换comName的值为要显示的组件名

import UserName from '../components/01/UserName'
import UserInfo from '../components/01/UserInfo'
export default {
    data(){
        return {
            comName: "UserName"
        }
    },
    components: {
        UserName,
        UserInfo
    }
}
</script>

vue内置component组件, 配合is属性, 设置要显示的组件名字

  1. 什么是动态组件?
    在同一个挂载点, 可以切换显示不同组件
  2. 如何使用动态组件?
    vue内置的component组件, 配合is属性 <component :is="组件名"></component>
  3. 如何切换?
    改变is属性的值, 为要显示的组件名即可

二、组件缓存

在频繁的切换动态组件 会导致 组件的频发创建和销毁,导致效率不高 

可以通过vue 内置的Keep-alive 组件包裹 component 组件 来解决

<div style="border: 1px solid red;">
    <!-- Vue内置keep-alive组件, 把包起来的组件缓存起来 -->
    <keep-alive>
        <component :is="comName"></component>
    </keep-alive>
</div>

keep-alive 组件有两个生命周期

activated - 激活  deactivated 失去激活状态

三、组件的激活和非激活状态

如何知道组件被切走了还是切回来?

通过 激活状态的生命周期 中的钩子函数

activated 激活 deactivated 失去激活状态来判断

 如果 不想给某个 组件设置 缓存怎么操作?

可以通过

include="组件Aname"  组件A会缓存,其他的不会被缓存

exclude=“组件Aname” 组件a 不会被换缓存 其他的组件缓存

   <!-- <keep-alive exclude="comTwoName">
        <components :is="comname"></components>
      </keep-alive> -->
      <keep-alive exclude="ComOnes">
        <components :is="comname"></components>
      </keep-alive>

四、组件插槽

组件里的数据不确定可以怎么做?

通过 slot 标签

以前折叠面板案例, 想要实现不同内容显示, 我们把折叠面板里的Pannel组件, 添加组件插槽方式

语法: 

组件内使用<slot></slot> 站位

使用组件时 <Pannel></Pannel> 夹着的地方 传入标签替换slot

 ①当组件内某一部分标签不确定怎么办?

用插槽技术

②插槽具体如何使用?

先在组件内使用slot 站位

③插槽运行效果?

传入的标签会替换掉slot 显示 如果没有传入会显示默认插槽里面的内容

④ 如何给插槽设置默认显示内容?

<slot>默认显示内容</slot>

⑤什么时候插槽默认内容会显示?

当组件不传入具体标签或者内容时

五、具名插槽

如果组件内2处以上不确定标签怎么办,可以通过给插槽起名解决!

v-slot一般用跟template标签使用 (template是html5新出标签内容模板元素, 不会渲染到页面上, 一般被vue解析内部标签)

语法?

①slot 使用name属性 区分名字

②template 配合v-slot 名字来分发对应标签

<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
        //设置名字
      <slot name="title"></slot>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
        //设置名字
     <slot name="content"></slot>
    </div>
  </div>
</template>

使用名字

<Pannel>
            //通过 v-slot:插槽名字
        <template v-slot:title>
          <h4>芙蓉楼送辛渐</h4>
        </template>
        <template v-slot:content>
          <img src="../assets/mm.gif" alt="">
          <span>我是内容</span>
        </template>
      </Pannel>
      <Pannel>
        //通过#插槽名字
        <template #title>
          <span style="color: red;">我是标题</span>
        </template>
        <template #content>
          <p>寒雨连江夜入吴,</p>
        
        </template>
      </Pannel>

使用插槽 名字 语法:

v-sloat:插槽名字  #插槽名字

  1. 组件内多处不确定的标签如何做?
    slot占位, 给name属性起名字来区分
    template配合v-slot:name分发要替换的标签
  2. v-slot: 可以简化成什么?
    #

六、作用域插槽

使用插槽时,想要使用组件内的变量?

子组件里面的值, 在插槽赋值时 在 父组件环境下使用?

语法:

①子组件,在slot 上绑定属性和子组件内的值

②使用组件,传入自定义标签,用template 和 v-slot = “ 自定义变量名”

③scope变量自动绑定 slot上所有的属性和值

<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
      <h4>芙蓉楼送辛渐</h4>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
     <slot :row="defaultObj">{{ defaultObj.defaultOne }}</slot>
    </div>
  </div>
</template>

<script>
// 目标: 作用域插槽
// 场景: 使用插槽, 使用组件内的变量
// 1. slot标签, 自定义属性和内变量关联
// 2. 使用组件, template配合v-slot="变量名"
// 变量名会收集slot身上属性和值形成对象
export default {
  data() {
    return {
      isShow: false,
      defaultObj: {
        defaultOne: "无名氏",
        defaultTwo: "小传同学"
      }
    };
  },
};
</script>

      <Pannel>
        <!-- 需求: 插槽时, 使用组件内变量 -->
        <!-- scope变量: {row: defaultObj} -->
        <template v-slot="scope">
          <p>{{ scope.row.defaultTwo }}</p>
        </template>
      </Pannel>

子组件内 设置 :row=“变量”

父组件

在 template 标签设置 v-slot = "scope" 来接收 slot 插槽的所有变量(scope变量: {row: defaultObj} -  )这种情况 在使用的时候 需要 scope.row.想要调用的变量名

或者 通过 v-slot = "row" row是自定义变量名

总结:

① 作用域插槽什么时候使用?

父组件 想要用子组件的变量

②口诀?

子组件在slot 上添加属性 和 子组件的值

使用组件出的template 配合 v-slot="变量名 " 收集 slot 身上所有的属性和值

作用域插槽使用场景?

了解作用域插槽使用场景, 自定义组件内标签+内容

案例: 封装一个表格组件, 在表格组件内循环产生单元格

准备MyTable.vue组件 – 内置表格, 传入数组循环铺设页面, 把对象每个内容显示在单元格里

准备UseTable.vue – 准备数据传入给MyTable.vue使用

components/06/MyTable.vue - 模板(直接复制)

<template>
  <div>
      <table border="1">
          <thead>
              <tr>
                  <th>序号</th>
                  <th>姓名</th>
                  <th>年龄</th>
                  <th>头像</th>
              </tr>
          </thead>
          <thead>
              <tr>
                  <td></td>
                  <td></td>
                  <td></td>
                  <td></td>
              </tr>
          </thead>
      </table>
  </div>
</template>

<script>
export default {

}
</script>

views/06_UseTable.vue - 准备数据, 传入给MyTable.vue组件里循环使用

list: [
    {
        name: "小传同学",
        age: 18,
        headImgUrl:
        "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
    },
    {
        name: "小黑同学",
        age: 25,
        headImgUrl:
        "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
    },
    {
        name: "智慧同学",
        age: 21,
        headImgUrl:
        "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
    },
],

正确做法:

在MyTable.vue的td中准备占位, 但是外面需要把图片地址赋予给src属性,所以在slot上把obj数据绑定

components/06/MyTable.vue  

<template>
  <div>
      <table border="1">
          <thead>
              <tr>
                  <th>序号</th>
                  <th>姓名</th>
                  <th>年龄</th>
                  <th>头像</th>
              </tr>
          </thead>
          <tbody>
              <tr v-for="(obj, index) in arr" :key="index">
                  <td>{{ index + 1 }}</td>
                  <td>{{ obj.name }}</td>
                  <td>{{ obj.age }}</td>
                  <td>
                      <slot :row="obj">
                          <!-- 默认值给上,如果使用组件不自定义标签显示默认文字 -->
                          {{ obj.headImgUrl}}
                      </slot>
                  </td>
              </tr>
          </tbody>
      </table>
  </div>
</template>

<script>
export default {
    props: {
        arr: Array
    }
}
</script>

在UseTable使用MyTable的时候, template上v-slot绑定变量, 传入img组件设置图片地址

<template>
  <div>
    <MyTable :arr="list"></MyTable>
    <MyTable :arr="list">
        <!-- scope: {row: obj} -->
       <template v-slot="scope">
            <a :href="scope.row.headImgUrl">{{ scope.row.headImgUrl }}</a>
       </template>
    </MyTable>
    <MyTable :arr="list">
       <template v-slot="scope">
            <img style="width: 100px;" :src="scope.row.headImgUrl" alt="">
       </template>
    </MyTable>
  </div>
</template>

<script>
import MyTable from "../components/06/MyTable";
export default {
  components: {
    MyTable,
  },
  data() {
    return {
      list: [
        {
          name: "小传同学",
          age: 18,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
        },
        {
          name: "小黑同学",
          age: 25,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
        },
        {
          name: "智慧同学",
          age: 21,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
        },
      ],
    };
  },
};
</script>

<style>
</style>

 

小结

我们为什么要使用作用域插槽?

可以让组件更加灵活的适用于不同的场景和项目

插槽可以自定义标签, 作用域插槽可以把组件内的值取出来自定义内容

七、组件name

name的作用

1、递归组件的(组件调用自身组件)

这个时候被递归的组件name必写

<template>
  <div>
    <childVue :list="arr" />
  </div>
</template>
<script>
import childVue from "./child.vue";

export default {
  components: {
    childVue,
  },
  data() {
    return {
      //无限极的数据
      arr: [
        {
          name: "一级",
          childArr: [
            {
              name: "二级",
            },
            {
              name: "二级",
              childArr: [
                { name: "三级" },
                {
                  name: "三级",
                  childArr: [{ name: "四级" }],
                },
              ],
            },
          ],
        },
        {
          name: "一级",
        },
        {
          name: "一级",
        },
      ],
    };
  },
  methods: {},
};
</script>
<style scoped></style>
<template>
  <!-- <div> -->
  <ul>
    <li v-for="(item, index) in list" :key="index">
      {{ item.name }}
      <!-- 用 v-if 判断 item 里面是不是还有孩子 如果有 通过组件 name 输出出里面的孩子 -->
      <template v-if="item.childArr">
        <ChildTree :list="item.childArr" />
      </template>
    </li>
  </ul>
  <!-- </div> -->
</template>
<script>
//场景:后台管理系统的左侧手风琴菜单
//作用:处理、展示无限极的数据
export default {
  name: "ChildTree",
  props: ["list"],
  data() {
    return {};
  },
  methods: {},
};
</script>
<style scoped></style>

2、组件的缓存keep-alive

一个组件需不需要被缓存,也是需要通过name属性来控制。

3、vue调试插件DevTools

显示组件的name,语义化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值