Vue组件进阶(动态组件,组件缓存,组件插槽,具名插槽,作用域插槽)与自定义指令

一、Vue组件进阶

1.1 动态组件

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

在这里插入图片描述

实现流程

在这里插入图片描述

代码

<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>
import UserName from '../components/01/UserName.vue'
import UserInfo from '../components/01/UserInfo.vue'
export default {
    components: {
        UserInfo,
        UserName
    },
    data() {
        return {
            comName: 'UserName' ,//准备一个变量
        }
    }
}
</script>

1.2 组件缓存

原因:频繁的切换会导致组件频繁创建和销毁,性能不高

  • 语法: Vue内置的keep-alive组件 包起来要频繁切换的组件
<div style="border: 1px solid red;">
    <keep-alive>
        <!-- Vue内置组件  包起来进行缓存 -->
        <component :is="comName"></component>
    </keep-alive>
</div>
 //dom更改后
    created() {
        console.log('username组件创建了');
    },
    //实例销毁
    destroyed() {
        console.log('username组件销毁了');
    },

1.3 组件激活和非激活

扩展2个新的生命周期方法

  • activated -- 激活时触发
  • deactivated -- 失去激活状态触发
 //组件缓存后  多了两个钩子函数
    activated() {
        console.log('username组件激活了');
    },
    deactivated() {
        console.log('username组件失去激活状态');
    }

1.4 组件插槽

通过 slot 标签, 让组件内可以接收不同的标签结构显示

在这里插入图片描述

语法

  • 1.组件内使用<slot></slot>进行占位
  • 2.使用组件时<Pannel></Pannel>夹着的地方,传入标签替换slot
    在这里插入图片描述

插槽默认内容

  • <slot>内放置内容, 作为默认显示内容
  • 不给组件传标签. slot内容原地显示
  • 给组件内传标签, 则slot整体被换掉

父组件代码

<Pannel>
    <img src="../../src/assets/logo.png" alt="">
    <span>我是图片</span>
</Pannel>
<Pannel>
    <p>寒雨连江夜入吴,</p>
    <p>平明送客楚山孤。</p>
    <p>洛阳亲友如相问,</p>
    <p>一片冰心在玉壶。</p>
</Pannel>
<Pannel></Pannel>

子组件代码

<div>
    <!-- 按钮标题 -->
    <div class="title">
        <h4>芙蓉楼送辛渐</h4>
        <span class="btn" @click="isShow = !isShow">
            {{ isShow ? "收起" : "展开" }}
        </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
        <slot>
            <!-- 没有传则显示默认内容 -->
            我是默认的显示内容
        </slot>
    </div>
</div>

1.5 具名插槽

一个组件内有2处以上需要外部传入标签的地方

  • 语法
    • 1.slot使用name属性区分名字
    • 2.template配合v-slot:名字来分发对应标签
  • v-slot; 可以简写为#
    在这里插入图片描述

父组件代码

<Pannel>
    <template v-slot:title>
        <h4>
            芙蓉楼送辛渐
        </h4>
    </template>
    <template v-slot:content>
        <img src="../../src/assets/logo.png" alt="">
        <span>我是图片111</span>
    </template>
</Pannel>

<Pannel>
    <template #title>
        <h4>
            v-slot:可简写成#号
        </h4>
    </template>
    <template #content>
        <img src="../../src/assets/logo.png" alt="">
        <span>我是图片222</span>
    </template>
</Pannel>

子组件代码

<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>

1.6 作用域插槽

在使用子组件时,父组件需要使用子组件里的变量

在这里插入图片描述

步骤

  • 1.子组件, 在slot上绑定属性和子组件内的值
  • 2. 父组件, 传入自定义标签, 用template和v-slot="自定义变量名"
  • 3. scope变量名自动绑定slot上所有属性和值
    • scope = {row: defaultObj}

在这里插入图片描述

父组件代码

<Pannel>
    <template v-slot="scope">
        <!-- scope变量{row:defaultObj} -->
        {{ scope.row.defaultTwo }}
    </template>
</Pannel>

子组件代码

<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: '木子'
            }
        };
    },
};

1.7 作用域插槽使用场景

在这里插入图片描述
在这里插入图片描述

父组件代码

<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 :src="scope.row.headImgUrl" alt="">
            </template>
        </Mytable>
    </div>
</template>

<script>
import Mytable from '../components/06/MyTable.vue'
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>

子组件代码

<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">
                    <td>{{ index + 1 }}</td>
                    <td>{{ obj.name }}</td>
                    <td>{{ obj.age }}</td>
                    <td>
                        <!-- 标签不确定 slot插槽占位 -->
                        <!-- 默认显示文字 -->
                        <slot :row="obj">{{ obj.headImgUrl }}</slot>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</template>
  
<script>
export default {
    props: {
        arr: Array
    }
}
</script>

二、自定义指令

2.1 自定义指令–注册

获取标签, 扩展额外的功能

  • 全局注册 main.js
//全局指令  到处直接使用
Vue.directive("gfocus", {
  inserted(el) {
    console.log('el', el);
    el.focus(); //触发标签的事件方法
  }
})
  • 局部注册
directives: {
        focus: {
            inserted(el) {
                el.focus()
            }
        }
    },

使用 v-指令名

<input v-focus type="text">

2.2 自定义指令-传参

语法

//注意:inserted方法 指令所在标签,被插入到网页上才会触发(一次)
//update方法 指令对应数据/标签更新时,此方法执行
//目标:自定义指令全局 传值
Vue.directive('color', {
  inserted(el, binding) {
    console.log('binding', binding);
    el.style.color = binding.value
  },
  update(el, binding) {
    el.style.color = binding.value

  }
})
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gik99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值