VUE3 插件的开发和使用

在构建 Vue 项目的过程中,离不开各种开箱即用的插件支持,用以快速完成需求,避免自己造轮子。

在 Vue 项目里,可以使用针对 Vue 定制开发的专属插件,也可以使用无框架依赖的通用 JS 插件,插件的表现形式也是丰富多彩,既可以是功能的实现,也可以是组件的封装,本章将从插件的使用到亲自开发一个小插件的过程,逐一讲解。

插件的安装和引入

在 前端工程化 十分普及的今天,可以说几乎所有要用到的插件,都可以在 npmjs 上搜到,除了官方提供的包管理器 npm ,也有很多种安装方式选择。

TIP

如果还不了解什么是包和包管理器,请先阅读 了解包和插件 一节的内容。

另外,每个包管理都可以配置镜像源,提升国内的下载速度,对此也可以先阅读 配置镜像源 一节了解。

虽然对于个人开发者来说,有一个用的顺手的包管理器就足够日常开发了,但是还是有必要多了解一下不同的包管理器,因为未来可能会面对团队协作开发、为开源项目贡献代码等情况,需要遵循团队要求的包管理机制(例如使用 Monorepo 架构的团队会更青睐于 yarn 或 pnpm 的 Workspace 功能)。

通过 npm 安装
npm 是 Node.js 自带的包管理器,平时通过 npm install 命令来安装各种 npm 包(比如 npm install vue-router ),就是通过这个包管理器来安装的。

如果包的下载速度太慢,可以通过以下命令管理镜像源:

# 查看下载源
npm config get registry

# 绑定下载源
npm config set registry https://registry.npmmirror.com

# 删除下载源
npm config rm registry
TIP

npm 的 lock 文件是 package-lock.json ,如果有管理多人协作仓库的需求,可以根据实际情况把它添加至 .gitignore 文件,便于统一团队的包管理。

通过 cnpm 安装
cnpm 是阿里巴巴推出的包管理工具,安装之后默认会使用 https://registry.npmmirror.com 这个镜像源。

它的安装命令和 npm 非常一致,通过 cnpm install 命令来安装(比如 cnpm install vue-router)。

在使用它之前,需要通过 npm 命令进行全局安装:

npm install -g cnpm

# 或者
# npm install -g cnpm --registry=https://registry.npmmirror.com
TIP

cnpm 不生成 lock 文件,也不会识别项目下的 lock 文件,所以还是推荐使用 npm 或者其他包管理工具,通过绑定镜像源的方式来管理项目的包。

通过 yarn 安装
yarn 也是一个常用的包管理工具,和 npm 十分相似, npmjs 上的包,也会同步到 yarnpkg 。

也是需要全局安装才可以使用:

npm install -g yarn

但是安装命令上会有点不同, yarn 是用 add 代替 install ,用 remove 代替 uninstall ,例如:

# 安装单个包
yarn add vue-router

# 安装全局包
yarn global add typescript

# 卸载包
yarn remove vue-router

而且在运行脚本的时候,可以直接用 yarn 来代替 npm run ,例如 yarn dev 相当于 npm run dev 。

yarn 默认绑定的是 https://registry.yarnpkg.com 的下载源,如果包的下载速度太慢,也可以配置镜像源,但是命令有所差异:

# 查看镜像源
yarn config get registry

# 绑定镜像源
yarn config set registry https://registry.npmmirror.com

# 删除镜像源(注意这里是 delete )
yarn config delete registry
TIP

yarn 的 lock 文件是 yarn.lock ,如果有管理多人协作仓库的需求,可以根据实际情况把它添加至 .gitignore 文件,便于统一团队的包管理。

通过 pnpm 安装
pnpm 是包管理工具的一个后起之秀,主打快速的、节省磁盘空间的特色,用法跟其他包管理器很相似,没有太多的学习成本, npm 和 yarn 的命令它都支持。

也是必须先全局安装它才可以使用:

npm install -g pnpm

目前 pnpm 在开源社区的使用率越来越高,包括接触最多的 Vue / Vite 团队也在逐步迁移到 pnpm 来管理依赖。

pnpm 的下载源使用的是 npm ,所以如果要绑定镜像源,按照 npm 的方式 处理就可以了

通过 CDN 安装
大部分插件都会提供一个 CDN 版本,让可以在 .html 文件里通过 script 标签引入。

比如:

<script src="https://unpkg.com/vue-router"></script>

插件的引入
除了 CDN 版本是直接可用之外,其他通过 npm 、 yarn 等方式安装的插件,都需要在入口文件 main.ts 或者要用到的 .vue 文件里引入,比如:

import {
    createRouter, createWebHistory } from 'vue-router'

因为本教程都是基于工程化开发,使用的 CLI 脚手架,所以这些内容暂时不谈及 CDN 的使用方式。

通常来说会有细微差别,但影响不大,插件作者也会在插件仓库的 README 或者使用文档里进行告知。

Vue 专属插件
这里特指 Vue 插件,通过 Vue Plugins 设计规范 开发出来的插件,在 npm 上通常是以 vue-xxx 这样带有 vue 关键字的格式命名(比如 vue-baidu-analytics)。

专属插件通常分为 全局插件 和 单组件插件,区别在于,全局版本是在 main.ts 引入后 use,而单组件版本则通常是作为一个组件在 .vue 文件里引入使用。

全局插件的使用
在本教程最最前面的时候,特地说了一个内容就是 项目初始化 ,在这里有提到过就是需要通过 use 来初始化框架、插件。

全局插件的使用,就是在 main.ts 通过 import 引入,然后通过 use 来启动初始化。

在 Vue 2 ,全局插件是通过 Vue.use(xxx) 来启动,而现在,则需要通过 createApp 的 use,既可以单独一行一个 use ,也可以直接链式 use 下去。

参数

use 方法支持两个参数:
在这里插入图片描述
基本的写法就是像下面这样:

// main.ts
import plugin1 from 'plugin1'
import plugin2 from 'plugin2'
import plugin3 from 'plugin3'
import plugin4 from 'plugin4'

createApp(App)
  .use(plugin1)
  .use(plugin2)
  .use(plugin3, {
   
    // plugin3's options
  })
  .use(plugin4)
  .mount('#app')

大部分插件到这里就可以直接启动了,个别插件可能需要通过插件 API 去手动触发,在 npm 包的详情页或者 GitHub 仓库文档上,作者一般会告知使用方法,按照说明书操作即可。

单组件插件的使用
单组件的插件,通常自己本身也是一个 Vue 组件(大部分情况下都会打包为 JS 文件,但本质上是一个 Vue 的 Component )。

单组件的引入,一般都是在需要用到的 .vue 文件里单独 import ,然后挂到 template 里去渲染,下面是一段模拟代码,理解起来会比较直观:

<template>
  <!-- 放置组件的渲染标签,用于显示组件 -->
  <ComponentExample />
</template>

<script lang="ts">
import {
    defineComponent, onMounted, ref } from 'vue'
import logo from '@/assets/logo.png'

// 引入单组件插件
import ComponentExample from 'a-component-example'

export default defineComponent({
   
  // 挂载组件模板
  components: {
   
    ComponentExample,
  },
})
</script>

通用 JS / TS 插件
也叫普通插件,这个 “普通” 不是指功能平平无奇,而是指它们无需任何框架依赖,可以应用在任意项目中,属于独立的 Library ,比如 axios 、 qrcode 、md5 等等,在任何技术栈都可以单独引入使用,非 Vue 专属。

通用插件的使用非常灵活,既可以全局挂载,也可以在需要用到的组件里单独引入。

组件里单独引入方式:

import {
    defineComponent } from 'vue'
import md5 from '@withtypes/md5'

export default defineComponent({
   
  setup() {
   
    const md5Msg = md5('message')
  },
})

全局挂载方法比较特殊,因为插件本身不是专属 Vue,没有 install 接口,无法通过 use 方法直接启动,下面有一小节内容单独讲这一块的操作,详见 全局 API 挂载。
本地插件
插件也不全是来自于网上,有时候针对自己的业务,涉及到一些经常用到的功能模块,也可以抽离出来封装成项目专用的插件。

封装的目的
举个例子,比如在做一个具备用户系统的网站时,会涉及到手机短信验证码模块,在开始写代码之前,需要先要考虑到这些问题:

1.很多操作都涉及到下发验证码的请求,比如 “登录” 、 “注册” 、 “修改手机绑定” 、 “支付验证” 等等,代码雷同,只是接口 URL 或者参数不太一样

2.都是需要对手机号是否有传入、手机号的格式正确性验证等一些判断

3.需要对接口请求成功和失败的情况做一些不同的数据返回,但要处理的数据很相似,都是用于告知调用方当前是什么情况

4.返回一些 Toast 告知用户当前的交互结果
常用的封装类型
常用的本地封装方式有两种:一种是以 通用 JS / TS 插件 的形式,一种是以 Vue 专属插件 的形式。

关于这两者的区别已经在对应的小节有所介绍,接下来来看看如何封装它们。
开发本地通用 JS / TS 插件
一般情况下会以通用类型比较常见,因为大部分都是一些比较小的功能,而且可以很方便的在不同项目之间进行复用。
项目结构
通常会把这一类文件都归类在 src 目录下的 libs 文件夹里,代表存放的是 Library 文件( JS 项目以 .js 文件存放, TS 项目以 .ts 文件存放)。

vue-demo
│ # 源码文件夹
├─src
│ │ # 本地通用插件
│ └─libs
│   ├─foo.ts
│   └─bar.ts
│
│ # 其他结构这里省略…
│
└─package.json

这样在调用的时候,可以通过 @/libs/foo 来引入,或者配置了 alias 别名,也可以使用别名导入,例如 @libs/foo 。
设计规范与开发案例
在设计本地通用插件的时候,需要遵循 ES Module 模块设计规范 ,并且做好必要的代码注释(用途、入参、返回值等)。
一般来说,会有以下三种情况需要考虑。
只有一个默认功能
如果只有一个默认的功能,那么可以使用 export default 来默认导出一个函数。

例如需要封装一个打招呼的功能:

// src/libs/greet.ts

/**
 * 向对方打招呼
 * @param name - 打招呼的目标人名
 * @returns 向传进来的人名返回一句欢迎语
 */
export default function greet(name: string): string {
   
  return `Welcome, ${
     name}!`
}

在 Vue 组件里就可以这样使用:

<script lang="ts">
import {
    defineComponent } from 'vue'
// 导入本地插件
import greet from '@libs/greet'

export default defineComponent({
   
  setup() {
   
    // 导入的名称就是这个工具的方法名,可以直接调用
    const message = greet('Petter')
    console.log(message) // Welcome, Petter!
  },
})
</script>

是一个小工具合集
如果有很多个作用相似的函数,那么建议放在一个文件里作为一个工具合集统一管理,使用 export 来导出里面的每个函数。

例如需要封装几个通过 正则表达式 判断表单的输入内容是否符合要求的函数:

// src/libs/regexp.ts

/**
 * 手机号校验
 * @param phoneNumber - 手机号
 * @returns true=是手机号,false=不是手机号
 */
export function isMob(phoneNumber: number | string): boolean {
   
  return /^1[3456789]\d{9}$/.test(String(phoneNumber))
}

/**
 * 邮箱校验
 * @param email - 邮箱地址
 * @returns true=是邮箱地址,false=不是邮箱地址
 */
export function isEmail(email: string): boolean {
   
  return /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/.test(
    email
  )
}

在 Vue 组件里就可以这样使用:

<script lang="ts">
import {
    defineComponent } from 'vue'
// 需要用花括号 {} 来按照命名导出时的名称导入
import {
    isMob, isEmail } from '@libs/regexp'

export default defineComponent({
   
  setup() {
   
    // 判断是否是手机号
    console.log(isMob('13800138000')) // true
    console.log(isMob('123456')) // false

    // 判断是否是邮箱地址
    console.log(isEmail('example@example.com')) // true
    console.log(isEmail('example')) // false
  },
})
</script>

TIP

类似这种情况,就没有必要为 isMob 、 isEmail 每个方法都单独保存一个文件了,只需要统一放在 regexp.ts 正则文件里维护。

包含工具及辅助函数
如果主要提供一个独立功能,但还需要提供一些额外的变量或者辅助函数用于特殊的业务场景,那么可以用 export default 导出主功能,用 export 导出其他变量或者辅助函数。

在 只有一个默认功能 这个打招呼例子的基础上修改一下,默认提供的是 “打招呼” 的功能,偶尔需要更热情的赞美一下,那么这个 “赞美” 行为就可以用这个方式来放到这个文件里一起维护。

// src/libs/greet.ts

/**
 * 称赞对方
 * @param name - 要称赞的目标人名
 * @returns 向传进来的人名发出一句赞美的话
 */
export function praise(name: string): string {
   
  return `Oh! ${
     name}! It's so kind of you!`
}

/**
 * 向对方打招呼
 * @param name - 打招呼的目标人名
 * @returns 向传进来的人名发出一句欢迎语
 */
export default function greet(name: string): string {
   
  return `Welcome, ${
     name}!`
}

在 Vue 组件里就可以这样使用:

<script lang="ts">
import {
    defineComponent } from 'vue'
// 两者可以同时导入使用
import greet, {
    praise } from '@libs/greet'

export default defineComponent({
   
  setup() {
   
    // 使用默认的打招呼
    const message = greet('Petter')
    console.log(message) // Welcome, Petter!

    // 使用命名导出的赞美
    const praiseMessage = praise('Petter')
    console.log(praiseMessage) // Oh! Petter! It's so kind of you!
  },
})
</script>

开发本地 Vue 专属插件
在 Vue 专属插件 部分已介绍过,这一类的插件只能给 Vue 使用,有时候自己的业务比较特殊,无法找到完全适用的 npm 包,那么就可以自己写一个!

项目结构
通常会把这一类文件都归类在 src 目录下的 plugins 文件夹里,代表存放的是 Plugin 文件( JS 项目以 .js 文件存放, TS 项目以 .ts 文件存放)。

vue-demo
│ # 源码文件夹
├─src
│ │ # 本地 Vue 插件
│ └─plugins
│   ├─foo.ts
│   └─bar.ts
│
│ # 其他结构这里省略…
│
└─package.json

这样在调用的时候,可以通过 @/plugins/foo 来引入,或者配置了 alias 别名,也可以使用别名导入,例如 @plugins/foo 。
设计规范
在设计本地 Vue 插件的时候,需要遵循 Vue 官方撰写的 Vue Plugins 设计规范 ,并且做好必要的代码注释,除了标明插件 API 的 “用途、入参、返回值” 之外,最好在注释内补充一个 Example 或者 Tips 说明,功能丰富的插件最好直接写个 README 文档。

开发案例
全局插件开发并启用后,只需要在 main.ts 里导入并 use 一次,即可在所有的组件内使用插件的功能。

下面对全局插件进行一个开发示范,希望能

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值