动态组件 & 插槽 & 自定义指令
1. 动态组件
1.1 什么是动态组件
动态组件指的是动态切换组件的显示与隐藏
。
1.2 如何实现动态组件渲染
vue 提供了一个内置的 <component>
组件,专门用来实现动态组件的渲染
。示例代码如下:
App.vue
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr />
<button @click="comName = 'Left'">展示 Left</button>
<button @click="comName = 'Right'">展示 Right</button>
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<!-- 1. component 标签是 vue 内置的,作用:组件的占位符 -->
<!-- 2. is 属性的值,表示要渲染的组件的名字 -->
<!-- 3. is 属性的值,应该是组件在 components 节点下的注册名称 -->
<component :is="comName"></component>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
data() {
return {
// comName 表示要展示的组件的名字
comName: 'Left'
}
},
components: {
// 如果在“声明组件”的时候,没有为组件指定 name 名称,则组件的名称默认就是“注册时候的名称”
Left,
Right
}
}
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
Left.vue
<template>
<div class="left-container">
<h3>Left 组件 --- {{ count }}</h3>
<button @click="count += 1">+1</button>
</div>
</template>
<script>
export default {
name: 'MyLeft',
data() {
return {
count: 0
}
},
created() {
console.log('Left 组件被创建了!')
},
destroyed() {
console.log('Left 组件被销毁了~~~')
},
}
</script>
<style lang="less">
.left-container {
padding: 0 20px 20px;
background-color: orange;
min-height: 250px;
flex: 1;
}
</style>
Right.vue
<template>
<div class="right-container">
<h3>Right 组件</h3>
</div>
</template>
<script>
export default {
// 当提供了 name 属性之后,组件的名称,就是 name 属性的值
// 对比:
// 1. 组件的 “注册名称” 的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
// 2. 组件声明时候的 “name” 名称的主要应用场景:结合 <keep-alive> 标签实现组件缓存功能;以及在调试工具中看到组件的 name 名称
name: 'MyRight'
}
</script>
<style lang="less">
.right-container {
padding: 0 20px 20px;
background-color: lightskyblue;
min-height: 250px;
flex: 1;
}
</style>
实验结果 发现当你轮流点击俩个按钮时 无法保存组件的状态 组件不会被缓存
1.3 使用 keep-alive 保持状态
默认情况下,切换动态组件时无法保持组件的状态
。此时可以使用 vue 内置的 组件保持动态组
件的状态。示例代码如下:
App.vue
在left.vue中添加几个函数进行验证 (跟created同级别)
实验结果
结论
.keep-alive 对应的生命周期函数
当组件被缓存
时,会自动触发组件的deactivated 生命周期函数
。
当组件被激活
时,会自动触发组件的activated
生命周期函数。
1.4 keep-alive 的include
属性
include 属性用来指定:只有名称匹配的组件
会被缓存。多个组件名之间使用英文的逗号
分隔:
1.5 动态组件的适用范围
可以进行导航栏的切换以及移动端网页的切换
点击left 显示left组件
点击right 显示right组件内容
2. 插槽
2.1 什么是插槽
插槽
(Slot)是 vue 为组件的封装者
提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分
定义为插槽。
可以把插槽认为是组件封装期间,为用户预留的内容的占位符
。
2.2 插槽的基本用法
在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符。示例代码如下:
右边这个组件中留了一个slot插槽
在左边使用这个组件时,中间用户自定义添加的东西加入到右边这个插槽中
注意
如果在封装组件时没有预留任何 插槽,则用户提供的任何自定义内容都会被丢弃
2.3 后备内容
封装组件时,可以为预留的 插槽提供后备内容(默认内容)
。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。示例代码如下:
<div class="left-container">
<h3>Left 组件</h3>
<hr />
<!-- 声明一个插槽区域 -->
<!-- vue 官方规定:每一个 slot 插槽,都要有一个 name 名称 -->
<!-- 如果省略了 slot 的 name 属性,则有一个默认名称叫做 default -->
<slot name="default">
<h6>这是 default 插槽的后备内容</h6>
</slot>
</div>
App.vue
<Left>
默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中
1. 如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令
2. v-slot: 后面要跟上插槽的名字 -->
3. v-slot: 指令不能直接用在元素身上,必须用在 template 标签上 -->
4. template 这个标签,它是一个虚拟的标签,只起到包裹性质的作用,但是,不会被渲染为任何实质性的 html 元素
5. v-slot: 指令的简写形式是 #
// 用户自定义的内容会寻找一个名字未default的slot中, 进行插槽
<template #default>
<p>这是在 Left 组件的内容区域,声明的 p 标签</p>
</Left>
2.4 具名插槽
如果在封装组件时需要预留多个插槽节点
,则需要为每个 插槽指定具体的 name 名称
。这种带有具体名称的插槽
叫做“具名插槽”。示例代码如下:
注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”
。
向具体的插槽添加内容
2.5 作用域插槽
在封装组件的过程中,可以为预留的 插槽绑定 props 数据,这种带有 props 数据的 叫做“作用域插槽
”。示例代码如下:
父组件中
子组件
父组件中可以通过v-slot=content的缩写
#content="msg"
来接收子组件的msg
数值
2.6 解构插槽
假如
子组件中有俩个值进行传送
<slot v-for="item in items" :user="item"></slot>
父组件
<template v-slot:default="{user}">
</template>
指定接收user的值 不接收items的数值
3 自定义指令
3.1 什么是自定义指令
vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。
3.2 自定义指令的分类
vue 中的自定义指令分为两类,分别是:
私有
自定义指令全局
自定义指令
3.3 私有自定义指令
在每个 vue 组件中,可以在 directives
节点下声明私有自定义指令。示例代码如下:
// 私有自定义指令的节点
directives: {
// 定义名为 color 的指令,指向一个配置对象
color: {
// 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
// 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
bind(el, binding) {
console.log('触发了 v-color 的 bind 函数')
el.style.color = binding.value
},
}
}
3.3.1 使用自定义指令
在使用自定义指令时,需要加上v-
前缀。示例代码如下:
3.3.2 为自定义指令动态绑定参数值
在 template 结构中使用自定义指令
时,可以通过等号(=)的方式,为当前指令动态绑定参数值
:
3.3.3通过 binding 获取指令的参数值
在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:
3.3.4 update 函数
bind 函数只调用 1 次
:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发
。 update 函数会在每次 DOM 更新
时被调用。示例代码如下:
3.3.5 全局自定义指令
全局共享的自定义指令需要通过“Vue.directive()
”进行声明,示例代码如下:
全局指令放在App.vue中
4 自定义事件
4.1 什么是自定义事件
在封装组件时,为了让组件的使用者
可以监听到组件内状态的变化
,此时需要用到组件的自定义事件
4.2 自定义事件的 3 个使用步骤
在封装组件时:
① 声明
自定义事件
②触发
自定义事件
在使用组件时:
③ 监听
自定义事件
4.2.1 声明自定义事件
开发者为自定义组件封装的自定义事件
,必须事先在 emits 节点中声明
,示例代码如下:
4.2.2 触发自定义事件
在 emits 节点下声明的自定义事件,可以通过 this.$emit(‘自定义事件的名称’) 方法进行触发,示例代码如下
4.2.3 监听自定义事件
在使用自定义的组件时,可以通过 v-on 的形式监听自定义事件。示例代码如下:
4.3 自定义事件传参
在调用 this.$emit() 方法触发自定义事件时,可以通过第 2 个参数为自定义事件传参,示例代码如下: