一、动态组件(了解)
- Vue3已经废除了动态组件,包括Vue2的过滤器也废掉了;
- 定义 :
- 多个组件 使用 同一个挂载点 ,并 动态切换;
- 使用场景 :
- 同一个挂载点 切换 不同组件 显示;
- 原理 :
v-if + v-else-if(只用v-if也是可以的)
;
- 实现步骤 :
- 设置 数据属性 ,来承载要显示的组件名:
- 注意点 :
- 数据属性属性值 === 组件名;
- 注意点 :
- 设置
挂载点<component :is="Vue数据属性"></component>
,使用is
来设置要 显示哪个组件 ;- 注意点 :
<component>
是 Vue内置组件;- 使用 v-bind 给 is属性 动态赋值;
- 注意点 :
- 根据需求,切换数据属性值;
- 设置 数据属性 ,来承载要显示的组件名:
二、组件缓存
-
使用
<component>
频繁切换组件 存在的问题:- 使用
<component>
内置组件频繁切换会导致组件一直在被创建和销毁 ,性能低(会将该组件所有的代码执行一遍),影响用户体验(如果有Ajax请求还会浪费用户流量); - 解决方法:⬇
- 使用
-
语法:
js<keep-alive> <component :is="Vue数据属性"></component> </keep-alive>
-
原理 :
- 使用Vue内置的
keepAlive
组件,包裹要频繁切换的组件,将其缓存起来 ,在切换的时候,不会再去创建,直接从缓存中获取(纯属废话了,原理这块可以去问问度娘,后面我会补充);
- 使用Vue内置的
-
组件缓存的好处 :
- 缓存组件的状态(数据不丢失);
- 提高性能(可以避免组件切来切去发起无效请求);
- 提升用户体验;
三、组件激活和非激活
- 配合
<keep-alive>
使用:- 使用了该标签,
activated
钩子替换created
,deactivated
钩子替换activated
钩子;
- 使用了该标签,
- 2个新的生命周期钩子函数 :
- 作用:
- 知道 缓存 的 组件 是 出现还是消失;
- activated : 激活时 自动触发 (类似于created()钩子);
- deactivated : 停用时 触发(类似于destroyed()钩子)
- 作用:
❗ 四、组件插槽
- 作用:
- 通过
slot
标签,让 组件内 可以 接收 不同的标签结构 显示 不同的效果 (使用slot
标签进行占位,要显示什么就直接插入到组件标签里面); - 解决了 组件内 标签 不确定 的问题;
- 通过
- Vue2官网 - 插槽;
4.1 匿名插槽
-
步骤: (先占位再分发)
- 组件内 标签不确定 的 地方 使用
<slot></slot>
占位; - 使用组件 时,在 组件标签内 插入 要显的 标签 即可(插入的标签 替换
slot
标签 );
- 组件内 标签不确定 的 地方 使用
-
原理 :
- 使用 组件标签 内的 标签结构 去替换 slot标签;
-
语法:
-
写法1 :
html<!-- 父组件 - 直接传递标签结构,不写template标签 --> <组件标签> 要传递的标签结构 </组件标签> <!-- 子组件 --> <!-- 使用 slot 标签占位 --> <slot></slot>
-
写法2 :
html<!-- 父组件 - 将传递的标签结构包裹在template中进行传递 --> <组件标签> <template> 要传递的标签结构 </template> </组件标签> ------------------------- <!-- 子组件: --> <!-- 使用 slot 标签占位 --> <slot></slot>
-
写法3 :
<slot>
不加name属性
,Vue 会 自动添加name属性
为default
;template标签
的v-solt
属性值就是default
;
html<!-- 父组件 - 将传递的标签结构包裹在template中,并给template添加 v-slot:default 进行传递 --> <组件标签> <!-- 不使用简写 --> <template v-slot:default></template> <!-- v-slot: 简写 --> <template #default></template> </组件标签> ------------------------- <!-- 子组件: --> <slot name="default"></slot>
-
-
示例展示:
-
总结 :
- 对比上面展示的效果图,得知 三种写法之间存在 优先级;
- 第三种写法的优先级最高;
- 第一种写法和第二种写法一样;
- 如果三种语法同时存在,只显示有
v-slot:default
或#default
的结构;
4.2 插槽默认内容
-
<slot>
内放置内容,作为插槽的 默认内容 ;<slot>
中夹着的 所有标签 或 文字 都属于 默认内容;
html<slot> 默认内容(可以是任意的) </slot>
-
在组件标签内传递了标签结构,就显示传递的;否则就显示默认的;
4.3 具名插槽
- 使用步骤:
- 在 子组件内 使用 slot标签 占位 并 添加 name属性(属性值自定义);
- 在 父组件内 ,子组件标签 内部, 用 template标签 包裹 要传递的标签结构 ,并给 template标签 添加 v-slot指令 (指令的属性值 === slot标签的 name 属性值 )标明要替换的slot标签(slot标签 与 template标签 是 相对应 的);
template
:Vue内置的组件,只起包裹作用,不会渲染到页面上;
- 注意 :
-
v-slot
语法 :html<!-- 不使用简写 --> <template v-slot:slot标签的name属性值> </template> <!-- 简写语法 --> <template #slot标签的name属性值> </template>
-
slot标签的name属性值 === templte标签v-slot指令的值
; -
任何没有被包裹在带有
v-slot
的<template>
中的内容都会被视为默认插槽的内容;
-
- 示例展示:
4.4 作用域插槽
- 使用步骤 :
- 子组件内 ,在
<slot>
标签 上 绑定自定义属性 并 设置属性值 ;- 属性名 :
- 自定义;
- 属性值 :
- Vue数据属性(data中的数据);
- 绑定的值 :
- 字符串:不需要使用指令;
- 变量:要使用
v-bind
指令(使用简写);
- 属性名 :
- 父组件内 ,先导入子组件,再使用该组件,传入自定义标签结构,用 template标签 包裹 要传入的内容 并 设置
v-slot:xxx = "子组件内slot上的自定义变量名"
; - 自定义变量名 自动绑定 slot标签 上 所有属性 和 值;
- 子组件内 ,在
- 🔺 注意两种写法的区别 :
v-slot:子组件内slot标签name属性值
➡ 具名插槽;v-slot:子组件内slot标签name属性值="子组件内slot标签的自定义变量名"
➡ 作用域插槽 ;- 对上面的简写:
#子组件内slot标签name属性值="子组件内slot标签的自定义变量名"
;
- 对上面的简写:
- 作用域插槽 :
- 带数据的插槽,带的是子组件内部的数据,带给父组件,父组件接收到子组件的数据,并且可以通过插槽回传给子组件;
- 作用域插槽是插槽的终极版 :
- 普通插槽只能做到给子组件分发内容,不能获取子组件的数据;
- 作用域插槽不仅可以给子组件分发内容还能拿到子组件的数据,再回传给子组件;
- 使用场景 :
- 插槽内容能够访问子组件内的数据;
- 示例展示:
- 作用域插槽是根据匿名插槽或具名插槽演变而来;
- ❗ 作用域插槽细节 :
v-slot:名字
: 名字 需要与 slot标签的name属性值 保持一致;v-slot:
➡ 可以简写成 #- 因为接收到的数据是对象,为了今后使用方便,可以在原地进行解构;
4.5 插槽总结
- 作用 :
- 解决组件内标签内容不确定的问题;
- 分类 :(3类)
- 匿名 / 默认插槽 :
- 作用 :
- 解决 组件内 只有一处 标签不确定 的 问题;
- 使用步骤 :
- 先占位 + 再分发内容(只分发内容,有三种写法):
- 写法1:不写
template
; - 写法2:写
template
,不写#
; - 写法3:写
template + #default
;
- 作用 :
- 具名插槽 :
- 作用 :
- 解决 组件内 有 两处及以上 标签不确定 的 问题;
- 使用步骤 :
- 先占位并添加name属性 + 分发内容并添加
#slot的name属性值
;
- 先占位并添加name属性 + 分发内容并添加
- 作用 :
- 作用域插槽 :
- 作用 :
- 标签不确定的问题 + 插槽内容使用子组件数据;
- 使用步骤:
- 传数据(slot上自定义属性名,属性值为传递的数据) + 接数据(template #slot的name属性值 = "变量名");
- 使用的时候,可以对对象进行解构。
- 作用 :
- 匿名 / 默认插槽 :
五、自定义指令
-
对 普通DOM元素 进行 原生操作 :
- ref;
- 自定义指令;
-
关于自定义指令的参数,请移步Vue2官网 - 自定义指令;
-
全局注册:
- 目标文件:
main.js
;
html// 所有的 Vue. 都要写在 new Vue 前面 // 定义 的时候 不加v-,使用 的时候必须 加v- Vue.directive('指令名', { // inserted:指令的钩子函数之一,表示指令所在DOM元素插入到真实DOM中自动 触发一次 // el:当前指令所在的DOM元素 inserted (el) { // 可以对el标签扩展额外功能 } }) ------------ // 携带数据 Vue.directive ('指令名', { // binding:记录了指令相关信息的对象 // 就关心binding.value这个属性值,里面记录的使指令后面表达式的值 inserted (el, binding) { } }) -------------- // update()也是指令钩子函数之一,表示指令所在组件数据变了的时候,每次都会执行一次 Vue.directive ('指令名', { inserted (el, binding) { 相同代码 }, undate (el, binding) { 相同代码 } })
- 目标文件:
-
局部注册:
- 目标文件:某个
.vue
文件;
htmlexport dafault { directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } }
- 目标文件:某个
-
自定义指令的使用 :
- 全局注册 :
- 该项目中任何
.vue
文件都是可以使用;
- 该项目中任何
- 局部注册 :
- 只能在当前
.vue
文件中使用;
- 只能在当前
- 全局注册 :
-
🔺 注意 :
- 定义 的时候 不加
v-
,使用 的时候必须 加v-
;
- 定义 的时候 不加
-
代码展示:
- 全局定义:
- 使用:
- 传数据并且可以修改数据: