Vue3
过滤器
vue3取消了过滤器这个功能,我们可以使用新增的全局变量方法来替换过滤器,这里以时间过滤举例,使用dayjs
- 首先定义过滤方法
import dayjs from 'dayjs'
const dateFilter = (val, format = 'YYYY-MM-DD') => {
if (!isNaN(val)) {
val = parseInt(val)
}
return dayjs(val).format(format)
}
export default app => {
app.config.globalProperties.$filters = {
dateFilter
}
}
- 然后在main.js引入,挂载到app上
- 使用方法如下:
<template #default="{ row }">
{{ $filters.dateFilter(row.openTime) }}
</template>
换肤功能
Elementplus组件换肤
首先要用到3个包:rgb-hex, css-color-function,formula.json,前两者是对颜色进行转化的包,后者是根据一个主色,将白色和黑色与主色进行一定比例的混合,生成颜色,用于换肤后基于主色的其他颜色替换。
- 获取
ElementPlus最新样式表,不赘述。 - 将
ElementPlus中要替换的部分打上标记,比如在ElementPlus中#3a8ee6为primary颜色,我们要替换所有基于#3a8ee6的ElementPlus中的颜色,下面的函数就是将和primary(#3a8ee6)有关的颜色进行替换
/**
* 返回 style 的 template
* 打上标记,即将#3a8ee6 全部替换为 'primary'
*/
const getStyleTemplate = (data) => {
// element-plus 默认色值
const colorMap = {
'#3a8ee6': 'shade-1',
'#409eff': 'primary',
'#53a8ff': 'light-1',
'#66b1ff': 'light-2',
'#79bbff': 'light-3',
'#8cc5ff': 'light-4',
'#a0cfff': 'light-5',
'#b3d8ff': 'light-6',
'#c6e2ff': 'light-7',
'#d9ecff': 'light-8',
'#ecf5ff': 'light-9'
}
// 根据默认色值为要替换的色值打上标记
Object.keys(colorMap).forEach((key) => {
const value = colorMap[key]
data = data.replace(new RegExp(key, 'ig'), value)
})
return data
}
- 根据选择换肤的主色调通过
formula.json生成颜色 - 根据上一步生成的颜色,将打上标记后的
ElementPlus样式表进行替换。
export const generateNewStyle = async (primaryColor) => {
const colors = generateColors(primaryColor)
let cssText = await getOriginalStyle()
// 遍历生成的样式表,在 CSS 的原样式中进行全局替换
Object.keys(colors).forEach((key) => {
cssText = cssText.replace(
new RegExp('(:|\\s+)' + key, 'g'),
'$1' + colors[key]
)
})
return cssText
}
- 将生成的样式表插入style标签中
国际化
切换语言后国际化未更改
监听保存的language变化后重新调用回调函数即可,可以编写一个这样的工具函数
/**
*
* @param {...any} cbs 所有的回调
*/
export function watchSwitchLang(...cbs) {
watch(
() => store.getters.language,
() => {
cbs.forEach(cb => cb(store.getters.language))
}
)
}
TagsView
麵包屑的右鍵菜單觸發事件
vue中有@contextmenu事件,右鍵觸發
麵包屑的關閉
麵包屑的關閉本質上就是對數據的處理,創建一個數組儲存麵包屑上的數據,每個對象包括路徑和路由元信息,同时也可以存储到本地存储中。面包屑的删除其他,删除右侧,删除当前无非都是对这个数组的数据进行处理。
处理基于路由的动态过渡
写法如下
<router-view v-slot="{ Component, route }">
<transition name="fade-transform" mode="out-in">
<keep-alive>
<component :is="Component" :key="route.path"></component>
</keep-alive>
</transition>
</router-view>
详情见router.vuejs.org/zh/guide/ad…
EXCEL导入
步骤
- 获取传入的EXCEL表文件数据
- 解析EXCEL文件
- 得到数据返回
获取传入的EXCEL文件数据
这里使用原生的<input type="file" />实现。定义两个props,一个是上传前回调beforeUpload,一个是成功回调onSuccess,像这类回调函数类型的props,在当前组件中,逻辑就是通过判断回调的返回成功与失败,决定是否继续往下进行操作。
读取文件使用的是FileReader对象,这里的逻辑先使用apiFileReader.readAsArrayBuffer()解析文件,然后在onload(文件读取完后),使用xlsx对其进行解析,获取解析后的数据。
const readerData = (rawFile) => {
loading.value = true
return new Promise((resolve, reject) => {
// https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
const reader = new FileReader()
// 启动读取指定的 Blob 或 File 内容
reader.readAsArrayBuffer(rawFile)
// 该事件在读取操作完成时触发
// https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/onload
reader.onload = (e) => {
// 1. 获取解析到的数据
const data = e.target.result
// 2. 利用 XLSX 对数据进行解析
const workbook = XLSX.read(data, { type: 'array' })
// 3. 获取第一张表格(工作簿)名称
const firstSheetName = workbook.SheetNames[0]
// 4. 只读取 Sheet1(第一张表格)的数据
const worksheet = workbook.Sheets[firstSheetName]
// 5. 解析数据表头
const header = getHeaderRow(worksheet)
// 6. 解析数据体
const results = XLSX.utils.sheet_to_json(worksheet)
// 7. 传入解析之后的数据
generateData({ header, results })
// 8. loading 处理
loading.value = false
// 9. 异步完成
resolve()
}
})
}
解析EXCEL文件
使用XLSX,注意两个通用要点:解析表头和上传后的时间解析错误
- 解析表头
/**
* 获取表头(通用方式)
*/
export const getHeaderRow = sheet => {
const headers = []
const range = XLSX.utils.decode_range(sheet['!ref'])
let C
const R = range.s.r
/* start in the first row */
for (C = range.s.c; C <= range.e.c; ++C) {
/* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
/* find the cell in the first row */
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
}
return headers
}
/**
* 解析 excel 导入的时间格式
*/
export const formatDate = (numb) => {
const time = new Date((numb - 1) * 24 * 3600000 + 1)
time.setYear(time.getFullYear() - 70)
const year = time.getFullYear() + ''
const month = time.getMonth() + 1 + ''
const date = time.getDate() - 1 + ''
return (
year +
'-' +
(month < 10 ? '0' + month : month) +
'-' +
(date < 10 ? '0' + date : date)
)
}
EXCEL导出
- 获取table数据
- 转化成相应格式
- 使用Export2Excel导出
局部打印
由于浏览器自带打印会打印整个页面,所以使用vue3-print-nb,传入id即可实现对应位置打印