一、动态组件(了解)
- Vue3已经废除了动态组件,包括Vue2的过滤器也废掉了;
- 定义:
- 多个组件 使用 同一个挂载点,并 动态切换;
- 使用场景:
- 同一个挂载点 切换 不同组件 显示;
- 原理:
v-if + v-else-if(只用v-if也是可以的);
- 实现步骤:
- 设置 数据属性 ,来承载要显示的组件名:
- 注意点:
- 数据属性属性值 === 组件名;
- 注意点:
- 设置
挂载点<component :is="Vue数据属性"></component>,使用is来设置要 显示哪个组件;- 注意点:
<component>是 Vue内置组件;- 使用 v-bind 给 is属性 动态赋值;
- 注意点:
- 根据需求,切换数据属性值;
- 设置 数据属性 ,来承载要显示的组件名:
二、组件缓存
- 使用
<component>频繁切换组件 存在的问题:- 使用
<component>内置组件频繁切换会导致组件一直在被创建和销毁,性能低(会将该组件所有的代码执行一遍),影响用户体验(如果有Ajax请求还会浪费用户流量); - 解决方法:⬇
- 使用
- 语法:
<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:
<!-- 父组件 - 直接传递标签结构,不写template标签 --> <组件标签> 要传递的标签结构 </组件标签> <!-- 子组件 --> <!-- 使用 slot 标签占位 --> <slot></slot> - 写法2:
<!-- 父组件 - 将传递的标签结构包裹在template中进行传递 --> <组件标签> <template> 要传递的标签结构 </template> </组件标签> ------------------------- <!-- 子组件: --> <!-- 使用 slot 标签占位 --> <slot></slot> - 写法3:
<slot>不加name属性,Vue 会 自动添加name属性为default;template标签的v-solt属性值就是default;
<!-- 父组件 - 将传递的标签结构包裹在template中,并给template添加 v-slot:default 进行传递 --> <组件标签> <!-- 不使用简写 --> <template v-slot:default></template> <!-- v-slot: 简写 --> <template #default></template> </组件标签> ------------------------- <!-- 子组件: --> <slot name="default"></slot>
- 写法1:
- 示例展示:
- 总结:
- 对比上面展示的效果图,得知 三种写法之间存在 优先级;
- 第三种写法的优先级最高;
- 第一种写法和第二种写法一样;
- 如果三种语法同时存在,只显示有
v-slot:default或#default的结构;
4.2 插槽默认内容
<slot>内放置内容,作为插槽的 默认内容;<slot>中夹着的 所有标签 或 文字 都属于 默认内容;
<slot> 默认内容(可以是任意的) </slot>- 在组件标签内传递了标签结构,就显示传递的;否则就显示默认的;
4.3 具名插槽
- 使用步骤:
- 在 子组件内 使用 slot标签 占位 并 添加 name属性(属性值自定义);
- 在 父组件内,子组件标签内部, 用 template标签 包裹 要传递的标签结构,并给 template标签 添加 v-slot指令(指令的属性值 === slot标签的 name 属性值)标明要替换的slot标签(slot标签 与 template标签 是 相对应的);
template:Vue内置的组件,只起包裹作用,不会渲染到页面上;
- 注意:
v-slot语法:<!-- 不使用简写 --> <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;
// 所有的 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文件;
export dafault { directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } } - 目标文件:某个
- 自定义指令的使用:
- 全局注册:
- 该项目中任何
.vue文件都是可以使用;
- 该项目中任何
- 局部注册:
- 只能在当前
.vue文件中使用;
- 只能在当前
- 全局注册:
- 🔺 注意:
- 定义 的时候 不加
v-,使用 的时候必须 加v-;
- 定义 的时候 不加
- 代码展示:
- 全局定义:
- 使用:
- 传数据并且可以修改数据:
- 全局定义: