前言

本文记录了一些Vue项目中常用的工具函数,为了工具函数的统一管理,统一将这些函数放到src目录下的utils文件夹里


一、自定义聚焦指令

1、方式一

mouted周期,ref+querySelector获取到input标签,调用focus()

2、方式二

自定义指令(局部)
directives:fofo(inserted),定义好以后在标签上使用, v-fofo

3、方式三

全局的自定义指令,推荐使用(复用性高)。
在main.js中导入后使用即可。
代码如下(示例):

import Vue from 'vue'

Vue.directive("fofo",{
  inserted(el) {
    // 判断拿到的元素名称
    if (el.nodeName === 'INPUT' || el.nodeName === 'TEXTAREA') {
      el.focus()
  	} else {
     // 尝试向内层获取一下
      el.querySelector('input').focus()
    }
  }
})

二、输入框防抖

1、需求

用户在输入框中输入内容的时候,要拿到用户输入的内容反馈给服务器,就需要需要监听输入框的input事件,但是当输入框的值发生改变就立即发送一次Ajax请求,会造成一些不必要的Ajax请求。当用户停止输入等待一定时间后,再向后台发送请求,就可以减少一些不必要的请求。

2、思路

当用户开始输入后,开启一个定时器,如果计时结束后,用户没有再次输入内容,就向后台发送Ajax请求。如果规定时间内,用户再次输入,就清除上一次的定时器,重新计时。

3、代码实现

这里用一个例子演示,理解实现原理后,可以将代码抽离出来。
代码如下(示例):

<template>
	<div>
        <input type="text" v-model="kw" @input="inputFn"/>
    </div>
</template>
<script>
export default{
    data(){
        return{
            kw:'',
            timer:null
        }
    },
    methods:{
        inputFn(){
            clearTimeout(this.timer)
      		this.timer = setTimeout(() => {
                if(this.kw === '') return
                // 这里可以发送Ajax请求,根据用户输入的关键字拿到后台返回的搜索联想列表
                console.log(this.kw)
            }, 1000) // 当用户停止输入内容一秒后会执行定时器内的逻辑,如果一秒内又写了内容就会重新计时
      	}
   	}
}
</script>

三、关键字高亮

1、需求

当用户在输入框搜索某个关键字后,将展示出来的联想列表中的关键字改变颜色,可以让用户更直观的看到想要的结果。

2、思路

封装一个lightFn函数,这个函数接收两个实参,
第一个是接收被修改字符串,第二个是要匹配的关键字

3、代码演示

代码如下(示例):

export const lightFn = (str, targetStr) => {
    // 忽略大小写且全局匹配
  const reg = new RegExp(targetStr, 'ig')
  return str.replace(reg, match => {
    return `<span style="color:red">${match}</span>`
  })
}

四、格式化Excel表格中存储的时间

1、需求

将需要导入的Excel表格中存储的时间,从Excel的格式转换为存储时的格式。

2、代码演示

此代码引自蓝雨溪,感谢这位大佬,这里收录一下~
代码如下(示例):

export function formatExcelDate(numb, format = '/') {
  const time = new Date((numb - 25567) * 24 * 3600000 - 5 * 60 * 1000 - 43 * 1000 - 24 * 3600000 - 8 * 3600000)
  time.setYear(time.getFullYear())
  const year = time.getFullYear() + ''
  const month = time.getMonth() + 1 + ''
  const date = time.getDate() + ''
  if (format && format.length === 1) {
    return year + format + month + format + date
  }
  return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}

五、 自定义指令控制按钮级别权限

1. 需求

Vue项目借助elementUI做后台管理系统,用户权限不同,看到的页面以及能使用的功能都不同。功能是通过点击链接或者按钮来实现的,既当用户没有对应权限时,就不展示其功能。一起来看看如何通过自定义指令控制按钮的创建吧~

2. 代码演示

  • 数组方法
    Array.includes()
    这个方法用来判断括号内传递的值是否在数组中存在,存在返回true,反之false。

  • 自定义指令中,binding.value可以拿到使用自定义指令的地方传入的值。

// 注册一个全局自定义指令 `v-allow`
Vue.directive('allow', {
  inserted: function(el, binding) {
     // 先拿到用户拥有的权限列表
    // 如果用户权限中有这一项
    if (用户拥有权限.includes(binding.value)) {
      // console.log('判断这个元素是否会显示', el, binding.value)
    } else {
       // 如果用户没有这项权限,就删除这个元素
      el.parentNode.removeChild(el)
      // 通过display来控制的话,不安全
      // el.style.display = 'none'
    }
  }
})

.vue文件中使用,自定义指令需要传入字符串

<template>
  <div>
  	<el-button
      v-allow="'xxx'"
      type="warning"
      @click="doSomeThing"
    >权限按钮</el-button>
  </div>
</template>

六、vue3自定义指令——图片懒加载

1. 思路

使用一个webAPI:IntersectionObserver
MDN文档:IntersectionObserver

IntersectionObserver()构造器创建并返回一个IntersectionObserver对象。 如果指定rootMargin则会检查其是否符合语法规定,检查阈值以确保全部在0.0到1.0之间,并且阈值列表会按升序排列。如果阈值列表为空,则默认为一个[0.0]的数组。

callback

  • 当元素可见比例超过指定阈值后,会调用一个回调函数,此回调函数接受两个参数:
  1. entries
    一个IntersectionObserverEntry对象的数组,每个被触发的阈值,都或多或少与指定阈值有偏差。
  2. observer
    被调用的IntersectionObserver实例。
  • 利用API监测图片是否处于可视区
  • 当图片出现在视口内,给图片src属性赋值
// 创建观察对象实例
// const observer = new IntersectionObserver(callback[, options])

const obs = new IntersectionObserver(([{isIntersecting}], observer) => {
    // entries = [{isIntersecting: true}]
    
}, {})
// 监听DOM元素
obs.observe(imgDom)
// 取消DOM监听
obs.unobserve(imgDom)

// callback 被观察dom进入可视区离开可视区都会触发
// - 两个回调参数 entries , observer
// - entries 被观察的元素信息对象的数组 [{元素信息},{}],信息中isIntersecting判断进入或离开
// - observer 就是观察实例
// options 配置参数
// - 三个配置属性 root rootMargin threshold
// - root 基于的滚动容器,默认是document
// - rootMargin 容器有没有外边距
// - threshold 交叉的比例

// 实例提供两个方法
// observe(dom) 观察哪个dom
// unobserve(dom) 停止观察那个dom

2. 代码演示

这里使用vue插件的方式,进行封装全局自定义指令

// 引入一张加载成功,但是图片地址出错显示给用户的图片
import defaultImg from '@/assets/images/xxx.png'
// 指令
const defineDirective = (app) => {
  // 图片懒加载指令
  app.directive('lazyload', {
    mounted (el, binding) {
      const observer = new IntersectionObserver(([{ isIntersecting }]) => {
        if (isIntersecting) {
          observer.unobserve(el)
          el.onerror = () => {
              el.src = defaultImg
          }  
          el.src = binding.value
        }
      }, {
        threshold: 0.01
      })
      observer.observe(el)
    }
  })
}

export default {
  install (app) {
    defineDirective(app)
  }
}

main.js中引入

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 导入自己封装的自定义指令
import myUI from './xxx'

createApp(App).use(store).use(router).use(myUI).mount('#app')

3. 使用

.vue结尾的文件中需要图片懒加载的地方,直接使用v-lazyload替换img标签上的src属性即可。

七、vue3批量注册组件

1. 思路

  • 使用 require 提供的函数 context 加载某一个目录下的所有 .vue 后缀的文件。
  • 然后 context 函数会返回一个导入函数 importFn
    • 它有一个属性 keys() 获取所有的文件路径
  • 通过文件路径数组,通过遍历数组,再使用 importFn 根据路径导入组件对象
  • 遍历的同时进行全局注册即可

2. 代码演示

// 其实就是vue插件,扩展vue功能,全局组件、指令、函数 (vue.30取消过滤器)
// 当你在mian.js导入,使用Vue.use()  (vue3.0 app)的时候就会执行install函数
// 导入指定文件夹文件夹下的所有组件
// 批量导入需要使用一个函数 require.context(dir,deep,matching)
// 参数:1. 目录  2. 是否加载子目录(true为加载,false为不加载)  3. 加载的正则匹配
const importFn = require.context('./', false, /\.vue$/)
// console.dir(importFn.keys()) 文件名称数组

export default {
  install (app) {
      // 批量注册全局组件
      importFn.keys().forEach(key => {
      // 导入组件
      const component = importFn(key).default
      // 注册组件
      app.component(component.name, component)
    })
  }
}

总结

本文持续更新,目录结构这里就省略了。如果小伙伴儿们觉得有用的话,记得点赞收藏哦~

更多推荐

Vue常用工具函数——(持续更新)