前言
本文记录了一些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
- 当元素可见比例超过指定阈值后,会调用一个回调函数,此回调函数接受两个参数:
- entries
一个IntersectionObserverEntry对象的数组,每个被触发的阈值,都或多或少与指定阈值有偏差。- 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)
})
}
}
总结
本文持续更新,目录结构这里就省略了。如果小伙伴儿们觉得有用的话,记得点赞收藏哦~