Vue3学习记录(七)--- 组合式API之指令和插件

news2024/11/14 17:57:14

一、内置指令

1、v-memo

​ 该指令是Vue3的v3.2版本之后新增的指令,用于实现组件模板缓存,优化组件更新时的性能。该指令接收一个固定长度的依赖值数组,在组件进行更新渲染时,如果数组中的每个依赖值都与上一次渲染时的值相同,则指令所在的模板元素及其子元素的更新渲染将会被跳过,甚至在创建虚拟DOM的阶段也会跳过这些节点的创建。只有当依赖值发生变化时,指令所在的模板元素及其子元素才会进行更新渲染。

<template>
  <div>
    <div v-memo="[testA,testB]">
      <h4>验证v-memo指令的作用</h4>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const testA = ref('testA')
const testB = ref('testB')
</script>

​ 如果v-memo指令接收的是一个空数组[],则其作用与v-once效果相同,仅在初始阶段渲染模板元素一次,在后续的更新渲染中,模板元素及其所有子元素将被当作静态内容并跳过更新渲染。

与v-for一起使用:

v-memo指令最常见的使用场景是与v-for渲染的长列表结合使用,例如:当组件的selected状态发生变化时,默认在更新创建虚拟DOM时会重复创建大量的的vnode,进行diff对比更新。当我们使用v-memo="[item.id === selected]"时,表示只有当前元素的selected状态发生变化时,才会更新当前元素,避免了大量无用vnode的创建。

<!-- [item.id === selected] 表示只有当前元素的selected状态发生变化时 才会更新当前元素 -->
<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
  <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
  <p>...more child nodes</p>
</div>
2、v-for和v-if

​ 在Vue2中v-forv-if不允许用在同一元素上,因为两者没有一个明确的优先级。在Vue3中虽然不推荐同时使用v-forv-if,但两者可以同时使用。

​ 当两者作用于同一元素时,v-if的优先级高,首先被执行,且v-if无法访问到v-for中的数据。因此还是建议将两者放在不同元素上使用:

<ul>
  <!-- 此时会报错 因为 item 是v-for中的属性 v-if中无法访问 -->
	<li v-for="item in list" v-if="item === 'aaa'">{{ item }}</li>
</ul>

<!-- 建议使用以下写法 -->

<ul>
	<template v-for="item in list">
		<li  v-if="item === 'aaa'">{{ item }}</li>
	</template>
</ul>
3、其余指令

​ 其余指令在Vue3中的功能与Vue2中功能相同,并未更新,此处就不展开讲述了。需要翻阅的可以查看我之前发布的内容:Vue2学习笔记。

二、自定义指令

1、基础用法

​ 除了Vue为我们提供的内置指令之外,还允许注册自定义指令,实现逻辑复用。但不建议过多使用自定义指令,只有当功能需要直接操作 DOM 时,才应该使用自定义指令。

​ 一个自定义指令由一个包含指令钩子函数的对象来定义。在 <script setup> 中,任何以 v 开头的驼峰式命名的变量都可以被用作一个自定义指令,例如:vFocus可以在模板中以v-focus指令的形式使用:

<template>
  <div>
    <!-- 在模板元素上使用自定义指令 -->
    <input type="text" v-focus />
  </div>
</template>

<script setup lang="ts">
// 声明一个自定义指令 作用为控制元素自动获取焦点
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

​ 在 <script setup> 中声明的自定义指令,只能在当前组件实例内使用。如果需要,也可以在mian.js中通过应用实例将自定义指令注册为全局指令,可在应用全局范围内使用:

// mian.js 文件
import { createApp } from 'vue'
import App from './App.vue'

// 创建应用实例
const app = createApp(App)
// 声明一个自定义指令 作用为控制元素自动获取焦点
const vFocus = {
  mounted: (el) => el.focus()
}
// 注册全局的自定义指令
app.directive('focus', vFocus)
2、在组件上使用自定义指令

​ 当自定义指令应用在组件上时,如果子组件只有一个根节点,则指令会被透传到子组件的根节点上;如果子组件含有多个根节点,自定义指令将会被忽略,同时会抛出一个警告。而且自定义指令不能通过$attrs对象传递给某个元素。

​ 不建议在组件上使用自定义指令。

3、指令钩子函数

​ 一个自定义指令对象中的钩子函数有七个可选的钩子函数,分别为:created()beforeMount()mounted()beforeUpdate()updated()beforeUnmount()unmounted()

const myDirective = {
  // 该钩子函数在绑定元素属性或事件监听器应用之前被调用
  created(el, binding, vnode, prevVnode) {},
  // 该钩子函数在绑定元素被挂载到页面之前被调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 该钩子函数在绑定元素及其后代节点挂载到页面之后被调用
  mounted(el, binding, vnode, prevVnode) {},
  // 该钩子函数在绑定元素更新前被调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 该钩子函数在绑定元素更新完成后调用
  updated(el, binding, vnode, prevVnode) {},
  // 该钩子函数在绑定元素从页面卸载之前被调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 该钩子函数在帮顶元素从页面卸载之后被调用
  unmounted(el, binding, vnode, prevVnode) {}
}

​ 每个钩子函数都接收四个参数,其中除了参数el之外,其余元素都是只读的。

​ 参数el表示指令绑定的DOM元素,可用于直接进行DOM操作,例如:

mounted: (el) => el.focus()

​ 参数binding是一个对象,其中包含以下属性:

  • value:指令接收的属性值。
  • oldValue:元素更新之前指令接收的属性值,仅在beforeUpdate()updated()钩子函数中可用。
  • arg:指令后面跟随的参数,元素以v-指令:参数的形式设置参数。
  • modifiers:对象结构,对象中存储了指令的修饰符,以{修饰符名称: true}的形式存储。
  • instance:指令所在的组件实例。
  • dir:指令的定义对象。

​ 参数vnode表示绑定元素对应的虚拟DOM。

​ 参数prevNode表示元素更新前所对应的虚拟DOM,仅在beforeUpdate()updated()钩子函数中可用。

update()钩子函数为例:
<template>
  <div>
    <!-- 在模板元素上使用自定义指令 -->
    <input type="text" v-focus:foo.aaa="'ccc'" />
  </div>
</template>

<script setup>
// 声明一个自定义指令 作用为控制元素自动获取焦点
const vFocus = {
  // 该钩子函数在绑定元素更新完成后调用
  updated(el, binding, vnode, prevVnode) {
    console.log('updated---el---',el);
    console.log('updated---binding---',binding);
    console.log('updated---vnode---',vnode);
    console.log('updated---prevVnode---',prevVnode);
  },
}
</script>

控制台输出结果:

在这里插入图片描述

4、简写形式

​ 如果一个自定义指令,只需要在mounted()updated()钩子函数中执行相同的代码,无需其他钩子函数参与,那么此时可以直接用一个函数来声明该自定义指令:

<template>
  <div>
    <!-- 在模板元素上使用自定义指令 -->
    <p v-color="'red'">自定义指令简写</p>
  </div>
</template>

<script setup lang="ts">
// 利用简写形式 声明一个自定义指令 作用为改变元素的字体颜色
const vColor = (el,binding) => {
  // 该函数会在 mounted 和 updated 时调用
  el.style.color = binding.value;
}
</script>
5、对象字面量属性值

​ 如果一个自定义指令需要接收多个属性值,则可以通过对象字面量的形式来传递属性值:

<template>
  <div>
    <p v-color="{ color: 'red', bgColor: 'green' }">自定义指令简写</p>
  </div>
</template>

<script setup lang="ts">
// 利用简写形式 声明一个自定义指令 作用为改变元素的字体颜色
const vColor = (el,binding) => {
  el.style.color = binding.value.color;
  el.style.backgroundColor = binding.value.bgColor;
}
</script>

三、插件

1、简介

​ 插件(Plugins)是Vue中一种重要的扩展机制,允许开发者向 Vue 应用示例添加全局级别的功能。但插件本身并不具有添加全局功能的能力,而是需要借助app.component()等方法去实现功能。所以在我看来插件更像是一个将main.js中功能抽出集合成的模块,然后通过导入模块,实现相应的功能,避免在main.js文件中书写过多的逻辑代码。

​ 插件常见的应用场景主要包括:

  • 引用第三方库,例如vue-router、ElementPlus等等。
  • 结合app.component()注册全局组件。
  • 结合app.directive()注册全局自定义指令。
  • 结合app.provide()提供全局依赖。
  • 结合app.config.globalProperties添加全局属性或全局方法。
2、基本用法

​ 插件可以是一个拥有install()安装方法的对象,也可以直接是一个安装方法本身。插件的安装方法接收两个参数:一个app表示插件安装到的Vue应用实例对象,一个options表示插件安装时的可选配置项:

const myPlugin = {
  install(app, options) {
    // app 是插件要要安装的应用实例
    // options 是插件安装时的可选配置项
  }
}

​ 在安装插件时,只需要将插件所在js文件导入到mian.js中,然后通过app.use()方法进行安装即可:

import { createApp } from 'vue'
// 导入插件
import myPlugin from './plugins/myPlugin.js'
const app = createApp({})
// 安装插件
app.use(myPlugin, {
  /* 可选的选项 这里面的内容会传递给插件install()方法 的 options 参数 */
})
3、自定义插件
创建插件:

​ 首先创建一个插件的js文件,内部书写插件的具体功能逻辑代码:

// logPlugin.js
const LogPlugin = {
  // 插件的安装方法
  install(app, options) {
    // 通过 provide() 方法传递全局方法
    app.provide('log', function (message) {
      // 如果传入了options.prefix,则在打印message时加上前缀
      if (options && options.prefix) {
        console.log(`${options.prefix}: ${message}`);
      } else {
        // 否则直接打印message
        console.log(message);
      }
    });
  }
}

// 导出插件
export default LogPlugin;
安装插件:

​ 在main.js导入插件文件,并通过app.use()进行安装:

import { createApp } from 'vue'

import App from './App.vue'
import LogPlugin from './plugins/logPlugin'

// 创建应用实例
const app = createApp(App)
// 将插件安装到应用示例上
app.use(LogPlugin, { prefix: '小助手提示您' })
app.mount('#app')

使用插件:

​ 在组件中需要通过inject()接收插件提供的全局方法:

<script setup>
import { inject } from 'vue';

const log = inject('log');

log('使用自定义插件的方法')
  
// 其他场景使用
</script>s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1534979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

web前端笔记+表单练习题+五彩导航栏练习题

web前端笔记 1-骨架快捷方式!enter<!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>骨架部分</titl…

刚进公司第一天-电脑环境搭建

写在前面 之前在公司做过一次开发小工具的分享&#xff0c;这两天有个同事找我学习一些小工具开发的知识&#xff0c;但是我发现他的基础是真的差&#xff0c;想学开发知识却连自己本地电脑环境都没弄好&#xff0c;确实&#xff0c;有些人工作了很久&#xff0c;由于自己工作中…

sentinel整合gateway实现服务限流

导入依赖: <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.csp</groupId><…

SpringCloudGateway之高性能篇

SpringCloudGateway之高性能篇 背景 在公司的开放平台中&#xff0c;为了统一管理对外提供的接口、处理公共逻辑、实现安全防护及流量控制&#xff0c;确实需要一个API网关作为中间层。 场景 统一接入点: API网关作为所有对外服务的单一入口&#xff0c;简化客户端对内部系统…

使用Go语言创建HTTP服务器并展示网页

使用Go语言创建一个简单的服务器时可以先建立一个项目根目录&#xff0c;随后在根目录中建立一个用于存放静态文件&#xff08;HTML/CSS/JavaScript&#xff09;的文件夹 GGboy&#xff0c;接下来输入命令初始化Go模块 go mod init GGboy // 项目名称是 GGboy 在出现 go.mod 文…

QT:三大特性

QT的三大特性&#xff1a; 1、信号与槽 2、内存管理 3、事件处理 1、信号与槽 当信号产生时&#xff0c;就会自动调用绑定的槽函数。 自定义信号: 类中需要添加O_OBJECT宏 声明: signals标签之下进行声明 定义&#xff1a; 信号不需要定义 …

Java项目基于Docker打包发布

一、后端项目 1.打包应用 mvn clean package -DskipTests 2、新建dockerfile文件 #基础镜像 FROM openjdk:8 #工作空间 WORKDIR /opt #复制文件 COPY wms-app-1.0-SNAPSHOT.jar app.jar #配置容器暴漏的端口 EXPOSE 8080 RUN ls #强制执行命令 ENTRYPOINT [ "java&quo…

谷粒商城——缓存的概念

1. 使用缓存的好处&#xff1a;减少数据库的访问频率&#xff0c;提高用户获取数据的速度。 2. 什么样的数据适合存储到缓存中&#xff1f; ①及时性、数据一致性要求不高的数据&#xff0c;例如物流信息、商品类目信息 ②访问量大更新频率不高的数据(读多、写少) 3. 读模式…

sentinel熔断规则详解

1、慢调用降级熔断 1.1、参数详解 最大RT&#xff1a;调用接口的最大时间。 比例阈值&#xff1a;超过了最大RT调用时间的请求的比例。 熔断时长&#xff1a;触发熔断后&#xff0c;熔断的时间 最小请求数据&#xff1a;每秒最少的请求数量&#xff0c;只有大于等于这个数…

电网的正序参数和等值电路(一)

本篇为本科课程《电力系统稳分析》的笔记。 本篇为第二章的第一篇笔记。 电力系统正常运行中&#xff0c;可以认为系统的三相结构和三相负荷完全对称。而对称三相的计算可以用一相来完成&#xff0c;其中所有给出的标称电压都是线电压的有效值&#xff0c;假定系统全部是Y-Y型…

基于Python3的数据结构与算法 - 16 链表

目录 链表 1. 创建链表 2. 链表的插入和删除 3. 双链表 4. 链表总结 链表 链表是由一系列节点组成的元素集合。每个节点包含两部分&#xff0c;数据域item和指向下一个节点得指针next。通过节点之间的相互连接&#xff0c;最终串联成一个链表。 class Node:def __init…

Unity访问安卓(Android)或苹果(iOS)相册

1.下载Native Gallery for Android & iOS插件 2.在场景中添加截图按钮、选择图片按钮、选择视频按钮等 using OpenCVForUnity.CoreModule; using OpenCVForUnity.ImgprocModule; using OpenCVForUnity.UnityUtils; using System.Collections; using System.Collections.Gen…

好用的GPTs:指定主题搜索、爬虫、数据清洗、数据分析自动化

好用的GPTs&#xff1a;指定主题搜索、爬虫、数据清洗、数据分析自动化 Scholar&#xff1a;搜索 YOLO小目标医学方面最新论文Scraper&#xff1a;爬虫自动化数据清洗数据分析 点击 Explore GPTs&#xff1a; Scholar&#xff1a;搜索 YOLO小目标医学方面最新论文 搜索 Scho…

C语言 swab 函数学习

swab函数交换字符串中相邻两个字节&#xff1b; void _swab( char *src, char *dest, int n ); char *src&#xff1a; 要拷贝、转换的字符串&#xff0c; char *dest&#xff0c;转换后存储到dest所表示的字符串&#xff0c; int n要拷贝、转换的字节数&#xff1b; 所…

交通事故档案管理系统|基于JSP技术+ Mysql+Java+Tomcat的交通事故档案管理系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

关于OceanBase中旁路导入的应用分享

背景 前段时间&#xff0c;在用户现场协助进行OceanBase的性能测试时&#xff0c;我注意到用户常常需要运用 insert into select 将上亿行的数据插入到一张大宽表里&#xff0c;这样的批量数据插入操作每次都需要耗时半个小时左右。对这一情况&#xff0c;我提议用户尝试采用旁…

福建科立讯通信 指挥调度管理平台 SQL注入漏洞复现(CVE-2024-2620、CVE-2024-2621)

0x01 产品简介 福建科立讯通信指挥调度管理平台是一个专门针对通信行业的管理平台。该产品旨在提供高效的指挥调度和管理解决方案,以帮助通信运营商或相关机构实现更好的运营效率和服务质量。该平台提供强大的指挥调度功能,可以实时监控和管理通信网络设备、维护人员和工作任…

SpringMVC | Spring MVC中的“拦截器”

目录: 拦截器 &#xff1a;1. 拦截器的 “概述”2. 拦截器的 “定义” (创建“拦截器”对象)3. 拦截器的 “配置” (让“拦截器”对象生效)4. 拦截器的 “执行流程”“单个拦截器”的执行流程“多个拦截器”的执行流程 作者简介 &#xff1a;一只大皮卡丘&#xff0c;计算机专业…

python云上水果超市的设计与实现flask-django-php-nodejs

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对云上水果超市进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套云上水果超市&#xff0c;帮助商家进行商品信…

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索&#xff08;dfs&#xff09;&#xff0c;就不得不说和广度优先搜索&#xff08;bfs&#xff09;有什么区别 先来了解dfs的过程&#xff0c;很多录友可能对dfs&#xff08;深度优先搜索&#xff09;&#xff0c;bfs&#xff08;广度优先搜索…