首页 前端知识 Vue-plugin 插件的应用

Vue-plugin 插件的应用

2024-07-01 23:07:14 前端知识 前端哥 789 737 我要收藏

前言

本文主要讲述 Vue 插件的主要应用场景以及如何开发一个 Vue2 版本的插件,并且举例一些在项目中的实际应用。


一、应用场景

插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。插件的功能范围没有严格的限制——一般有下面几种:

  1. 添加全局方法或者 property。如:vue-custom-element
  2. 添加全局资源:指令/过滤器/过渡等。如 vue-touch
  3. 通过全局混入来添加一些组件选项。如 vue-router
  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

二、开发插件

  1. 定义一个插件

一个插件可以是一个拥有 install() 方法的对象,也可以直接是一个安装函数本身。插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件选项
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}
  1. 注册一个插件

通过全局方法 Vue.use() 注册插件,需要在调用 new Vue() 启动应用之前注册,它会自动阻止多次注册相同插件,调用时也可传入一个可选的选项对象

// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

// 或者传入选项对象
Vue.use(MyPlugin, { someOption: true })

new Vue({
  // ...组件选项
})

三、在项目中应用

文中涉及的工具函数请参考:https://blog.csdn.net/qq_42966167/article/details/136479222

1.添加全局指令/过滤器

plugins/directive/install.js

import { toThousands } from '@/util';

let directives = {}

directives.color = (el, binding) => {
  el.style.color = binding.value
}

directives.width = (el, binding) => {
  el.style.width = Number.isFinite(binding.value) ? binding.value + 'px' : binding.value
}

directives.height = (el, binding) => {
  el.style.height = Number.isFinite(binding.value) ? binding.value + 'px' : binding.value
}

directives.toThousands = (el, binding) => {
  el.innerHTML = toThousands(binding.value, binding.arg);
}

export default {
  install: Vue => {
    for (let k of Object.keys(directives)) {
      Vue.directive(k, directives[k])
    }
  }
}

plugins/filter/install.js

import { toThousands, thousandToNum, formatDate } from '@/util'

let filters = {}

// 千分位显示
filters.toThousands = (value, precision = 2) => {
  return toThousands(value, precision);
}

// 千分位转数字
filters.thousandToNum = value => {
  return thousandToNum(value);
}

// Date 转指定格式的时间字符串
filters.formatDate = (date, format) => {
  return formatDate(date, format);
}

export default {
  install: Vue => {
    for (let k of Object.keys(filters)) {
      Vue.filter(k, filters[k])
    }
    // 挂载到原型上
    Vue.prototype.$filter = filters
  }
}

2. 组件封装成插件

项目中通常都会使用到 Loading 加载组件和 Message 消息提示框组件等,可将此类组件封装成插件,挂在到 Vue.prototype 上作为实例方法进行调用。此项目中使用 Element-UI 组件进行二次封装。

plugins/loading/install.js

import { Loading } from 'element-ui'

let loadingInstance = null

const loading = {
  show: (params = {}) => {
    let opts = Object.assign({
      fullscreen: true,
      background: 'rgba(255,255,255,0.5)'
    }, params)
    loadingInstance = Loading.service(opts)
  },
  close: () => {
    if (loadingInstance) {
      loadingInstance.close()
    }
  }
}

export default {
  install: Vue => {
    Vue.prototype.$loading = loading
  }
}

plugins/message/install.js

import { Message } from 'element-ui'

const closeMessage = () => {
  try {
    Message.closeAll()
  } catch (err) {
    console.warn('Too Frequent!')
  }
}

/**
 * @param msg 消息提示的内容
 * @param args 消息的可配置项
 */
const message = {
  info: (msg = '', args = {}) => {
    let config = { message: msg, duration: 0, showClose: true, ...args }
    closeMessage()
    Message.info.apply(Message.info, [config])
    return true
  },
  // 成功的提示信息设置默认2s后关闭
  success: (msg = '', args = {}) => {
    let config = { message: msg, duration: 2000, ...args }
    closeMessage()
    Message.success.apply(Message.success, [config])
    return true
  },
  warning: (msg = '', args = {}) => {
    let config = { message: msg, duration: 0, showClose: true, ...args }
    closeMessage()
    Message.warning.apply(Message.warning, [config])
    return false
  },
  error: (msg = '', args = {}) => {
    let config = { message: msg, duration: 0, showClose: true, ...args }
    closeMessage()
    Message.error.apply(Message.error, [config])
    return false
  }
}

export default {
  install: Vue => {
    Vue.prototype.$message = message
  }
}

3. 封装插件简化繁琐重复事项

3.1 敏感信息脱敏显示

在项目中需要对一些用户的敏感信息进行加密传输,并且解密之后需要根据规则对这些重要信息进行脱敏显示,要求如下:

1)身份证号码:保留前3位和后4位
如441*********4613

2)手机号码:保留前3位和后2位
如136******73

固定电话:区号不隐藏,7-8位电话号码保留最后3位
如0756-****888

3)银行卡账号:保留前3位和后4位
如621*******5213

4)E-MAIL:保留前2位和@后缀
如li****@ygsoft.com

5)住址:中间数字脱敏
如珠海市**号楼101

6)出生日期:隐藏中间4位
如19****15

7)姓名:3个字以内隐藏第1个字,4-6个字隐藏前2个字,大于6个字隐藏第3-6个字

plugins/desensitize/install.js

/**
 * 脱敏处理函数
 * @param {string} input - 需要脱敏处理的数据
 * @param {string} type - 数据类型,包括 'email', 'id', 'bankCard', 'address', 'birthdate', 'name', 'phone', 'custom'(不脱敏)
 * @return {string} 脱敏后的数据
 */
function maskData(input, type = 'phone') {
  if (typeof input !== 'string') return input
  const { securityEncryption } = session.get('THEME_CONFIG') || {}
  // 与服务端商定加解密方式
  input = decrypt(input)
  // 只解密不脱敏
  if (type === 'custom') return input
  // 地址脱敏 中间的数字进行脱敏 明月小区*单元**号楼101
  if (type === 'address') return input.replace(/(\d+)(?=\D)/g, match => '*'.repeat(match.length))
  let start, end
  switch (type) {
    case 'email': {
      // 邮箱,保留前两位和 "@" 后的所有字符
      const [localPart, domain] = input.split('@')
      if (localPart.length > 2) {
        start = 2
        end = domain.length + 1      }
      break
    }
    case 'id':
    case 'bankCard': {
      // 身份证号或银行卡号,保留前三位和后四位
      start = 3
      end = 4
      break
    }
    case 'birthdate': {
      // 出生日期,隐藏中间四位
      start = 2
      end = 2
      break
    }
    case 'name': {
      // 姓名,3个字以内隐藏第1个字,4-6个字隐藏前2个字,大于6个字隐藏第3-6个字
      const length = input.length
      if (length <= 3) {
        start = 0
        end = length - 1
      } else if (length <= 6) {
        start = 0
        end = length - 2
      } else {
        start = 2
        end = length - 6
      }
      break
    }
    default: // phone 包含手机号和固定电话
      // 手机号,保留前三位和后两位,电话号码保留区号和后三位
      // telRegExp-固定电话正则 phoneRegExp-手机号正则
      if (telRegExp.test(input) && !phoneRegExp.test(input)) {
        let matchRes = input.match(telRegExp)
        start = matchRes[1].length
        end = matchRes[2].length
      } else {
        start = 3
        end = 2
      }
  }
  // 计算被脱敏处理后的字符的长度
  let maskLength = input.length - start - end
  // 使用正则表达式进行脱敏处理
  const reg = new RegExp(`^(.{${start}}).*(.{${end}})$`)
  return input.replace(reg, `$1${'*'.repeat(maskLength)}$2`)
}

export default {
  install: Vue => {
    Vue.prototype.$maskData = maskData
  }
}

3.2 记录审计日志

用户在前端界面点击某个操作,需要记录当前操作的审计日志,例如用户点击了列表页的查询按钮,需要记录以下内容:在XXX页面,执行查询/新增/删除/更新等操作,操作内容:查询XXX,查询条件包含:XXX,操作结果:成功/失败。审计日志的内容由前端拼接,然后调用后端接口保存到数据库。
对于一些拼接审计日志等内容,涉及到比较多的重复性工作,定义一个 ActLog 类,类中包含了对应操作类型的实例方法,使用 Vue 插件的方式把将 ActLog 的实例挂载到 Vue 的原型上。

plugins/actLog/install.js

import http from '@/service/http'

class ActLog {
  // 查询
  query(params = {}, status = true) {
    params = this._setParams(params, status)
    let content = `${params.path},执行查询操作,`
    if (params.content) {
      content += `操作内容:${params.content},`
    }
    content += `操作结果:${params.result}`
    this._save(content, params.auditId)
  }

  // 新增
  add(params = {}, status = true) {
     // ...
  }

  // 更新
  update(params = {}, status = true) {
    // ...
  }

  // 删除
  delete(params = {}, status = true) {
    // ...
  }

  other(params = {}, status = true) {
    // ...
  }

  _setParams(params = {}, status = true) {
    params = Object.assign({
      path: '', // 操作路径
      content: '', // 日志内容
      auditId: '', // 审计ID
      gid: '', // 操作唯一标识
      result: '成功'
    }, params)
    params.path += '页面'
    if (!status) params.result = '失败'
    return params
  }

  // 调接口保存
  _save(content = '', auditId = '') {
    http.post('createLog', { auditId, content })
  }
}

export default {
  install: Vue => {
    Vue.prototype.$actLog = new ActLog()
  }
}

注册插件

将所有的插件都存放到 plugins 目录下,使得文件结构更清晰,易于维护,然后可以借助 require.context 遍历所有的 plugins 目录下的所有 install.js,然后使用 Vue.use 进行注册。

总结

  1. 使用 Vue 插件方便给 Vue 添加全局功能,把一些常用的工具函数、全局组件、指令、过滤器等以插件的形式注册到 Vue 的实例或者原型上,简化了调用方式,对于工具函数等无需每次引用之后再调用。
  2. 将这些插件都放到 plugins 目录下,使得目录结构更加清晰,易于维护。
  3. 不建议将过多的工具函数,比如一些不常用的挂载到 Vue 上,使得 Vue 对象太过冗余。
转载请注明出处或者链接地址:https://www.qianduange.cn//article/13746.html
标签
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!