Vue 系列笔记第五篇。本文参考:>> 黑马程序员 Vue 全套视频教程
系列文章阅读 📑📑
>> Vue「一」—— 前端工程化 、webpack 的基本使用及常用配置
>> Vue「二」—— vue 基本使用 、vue 指令 、vue 过滤器
>> Vue「三」—— vue 侦听器、vue 计算属性、vue-cli、vue 组件
>> Vue「四」—— 组件生命周期、数据共享
>> Vue「五」—— 动态组件、插槽、自定义指令
>> Vue「六」—— 前端路由、vue-router
🐾 文章内容预览
一、动态组件1. 什么是动态组件2. 使用 keep-alive 保持状态3. keep-alive 对应的生命周期函数4. include 和 exclude 属性5. name 名称二、插槽1. 什么是插槽2. 具名插槽3. 作用域插槽三、自定义指令1. 私有自定义指令2. 为自定义指令动态绑定参数值3. update 函数4. 函数简写5. 全局自定义指令一、动态组件
1. 什么是动态组件
动态组件指的是 动态切换组件的显示与隐藏 。vue 提供了 <component> 组件,它相当于组件的占位符,专门用来实现动态组件的渲染。
// is 属性的值,表示要渲染的组件的名字<component :is="comName"></component>data() {return {// comName 表示要展示的组件的名字comName: "Left",};},
上面这段代码即可实现在<component>
的位置渲染指定名称的组件,is
属性的值即为要渲染组件的名字。
2. 使用 keep-alive 保持状态
默认情况下,切换动态组件时 无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态。<keep-alive> 会把内部的组件进行缓存,而不是销毁组件。
<keep-alive><component :is="comName"></component></keep-alive>
上面这段代码使得 comName 对应名称的组件不会重复的创建和销毁,即使在该组件被隐藏时也不会被销毁,而是被缓存进内存中暂时失活。
3. keep-alive 对应的生命周期函数
当组件 被缓存 时,会自动触发组件的 deactivated 生命周期函数。当组件 被激活 时,会自动触发组件的 activated 生命周期函数。// 当组件第一次被创建的时候,既会执行 created 生命周期,也会执行 activated 生命周期// 当时,当组件被激活的时候,只会触发 activated 生命周期,不再触发 created。因为组件没有被重新创建activated() {console.log("组件被激活了,activated");},deactivated() {console.log("组件被缓存了,deactivated");},
4. include 和 exclude 属性
include 属性用来指定:只有 名称匹配的组件 会被缓存。多个组件名之间使用英文的逗号分隔。
<keep-alive include="Left, Right"><component :is="comName"></component></keep-alive>
或者,通过 exclude 属性指定哪些组件不需要被缓存。但是,不可以同时使用 include 和 exclude 这两个属性。
<keep-alive exclude="Left"><component :is="comName"></component></keep-alive>
5. name 名称
在组件声明时可以指定 name 属性,声明之后 name 属性的值就是组件的名称。
// Left.vueexport default {name: "MyLeft",};
name 属性指定后,在调试工具中所看到的组件名即为 name 属性的值。
二、插槽
1. 什么是插槽
插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把 不确定的、希望由用户指定的部分 定义为插槽 。
在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符。之后在使用该组件时,组件标签中的内容会被填充到 <slot> 的位置上。实现用户自己定义组件的 UI 结构。
页面展示效果如下,可以发现 <Left> 标签中的内容,自动被填充到了 <slot> 的位置上:
2. 具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 属性。这种带有具体名称的插槽叫做 “ 具名插槽 ”。
<div class="left-container"><header><!-- 页头 --><slot name="header"></slot></header><main><!-- 主体 --><slot></slot></main><footer><!-- 页脚 --><slot name="footer"></slot></footer></div>
如果省略 name 属性,其默认名称为 defalut 。在默认情况下,使用组件时,提供的内容都会被填充到 defalut 插槽中。
如何为具名插槽提供内容呢?
我们可以在一个<template>
元素上使用v-slot
指令,并以v-slot
的参数的形式提供其名称。
<Left><template v-slot:header><h2>滕王阁序</h2></template><template v-slot:default><p>豫章故郡,洪都新府</p><p>星分翼轸,地接衡庐</p><p>襟三江而带五湖,控蛮荆而引瓯越</p></template><template v-slot:footer><p>落款:王勃</p></template></Left>
❗❗ 注意:v-slot
指令不能使用在元素身上,必须放在<template>
或者是组件上面。同时,这里的<template>
只是一个虚拟的标签,它只起到包裹元素的作用,不会渲染成任何实质的 HTML 元素。
v-slot 有简写形式
跟v-on
和v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容v-slot:
替换为字符#
。
<template v-slot:header></template><!--等价于下面写法--><template #header></template>
3. 作用域插槽
在封装组件的过程中,可以为预留的 <slot> 插槽绑定数据,这种带有额外数据的插槽就被称为 作用域插槽 。
<!-- Left组件 --><slotname="content"msg1="hello vue.js"msg2="hello vue.js"msg3="hello vue.js"></slot>
其他组件引入该组件为该插槽填充内容时,就可以使用变量来接收绑定的数据。
<!-- 其他组件中引入 Left 组件--><Left><template #content="scope"><p>{{ scope }}</p><p>{{ scope.msg1 }}</p><p>{{ scope.msg2 }}</p><p>{{ scope.msg3 }}</p></template></Left>
这里使用形参 scope 来接收的数据,接收来的数据是一个对象。其实也可以使用其他变量名,只不过 scope 显得更专业一些。
页面效果如下:
注意:接收数据的形参也可以考虑用解构赋值的形式:
<template #content="{ msg1, msg2, msg3 }"><p>{{ msg1 }}</p><p>{{ msg2 }}</p><p>{{ msg3 }}</p></template>
上面插槽中属性提供的数据是固定的,你也可以将属性值绑定为 props 或 data 中数据。
三、自定义指令
vue 官方提供了v-text
、v-for
、v-model
、v-if
等常用的指令,除此之外 vue 还允许开发者自定义指令。
vue 中的自定义指令分为两类,分别是:
私有自定义指令全局自定义指令
1. 私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明 私有自定义指令 。
// 私有自定义指令的节点directives: {// 定义名为 color 的指令,指向一个配置对象color: {// 当指令第一次绑定到元素上时,会触发 bind 函数// el 是指令所绑定的 DOM 元素bind(el) {el.style.color = "red";},},},
❗❗ 注意:所定义的指令名称无需加v-
,如上代码v-color
所对应的指令名为color
。同时,定义的指令中含有bind(el)
函数,当指令第一次绑定到元素上时,会自动执行此函数。该函数中参数el
表示指令所在的 DOM 元素。
2. 为自定义指令动态绑定参数值
在template
结构中使用自定义指令时,可以通过等号=
的方式,为当前指令动态绑定参数值。之后,通过binding
获取指令的参数值。具体使用如下:
<h1 v-color="color">App 根组件</h1>
data() {return {color: "blue",// 可以动态传值};},directives: {color: {bind(el, binding) {el.style.color = binding.value;},},},
其中,binding
参数是一个对象,包含有color
的属性值:
3. update 函数
前面所说的bind
函数只调用 1 次,也就是指令第一次绑定到元素时被调用。而当 DOM 更新时bind
函数不会被触发。如果要每次更新后都要触发,可以利用 update 函数, update 函数会在每次 DOM 更新时被调用。
color: {// 第一次绑定时触发bind(el, binding) {console.log(binding);el.style.color = binding.value;},// 每次 DOM 更新时触发update(el, binding) {console.log(binding);el.style.color = binding.value;},},
❗❗ 注意:update
函数在刚绑定到元素身上时不会调用,只要当 DOM 元素更新时才会被触发。
4. 函数简写
如果bind
和update
函数中的逻辑完全相同,则 对象格式 的自定义指令可以简写成 函数格式 。
directives: {// 相当于 bind 和 update 叠加color(el, binding) {el.style.color = binding.value;},},
5. 全局自定义指令
全局共享的自定义指令需要通过Vue.directive()
进行声明,注意声明代码应该放在 main.js 文件 中。
// main.jsVue.directive('color', function(el, binding) {el.style.color = binding.value})