实用方法随笔记录

14 阅读2分钟

封装页面切换hooks

本 hooks 主要是将需要重复书写上一页下一页的切换函数进行封装

// composables/usePagination.ts
export function usePagination(fetchCallback: () => void) {
  const pageNum = ref(1)
  const pageSize = ref(20)

  /**
   * pageSize 改变触发
   */
  const handleSizeChange = (size: number) => {
    pageSize.value = size
    fetchCallback()
  }

  /**
   * 页码改变触发
   */
  const handleCurrentChange = (page: number) => {
    pageNum.value = page
    fetchCallback()
  }

  return {
    pageNum,
    pageSize,
    handleSizeChange,
    handleCurrentChange,
  }
}

使用

// 分页 hooks 封装 传入请求数据函数
const { pageNum, pageSize, handleCurrentChange, handleSizeChange } = usePagination(getListData)

封装全局 loading

本 hooks 是封装全局的 loading 感觉 element-plus 进行封装

// composables/useGlobalLoading.ts
import { ElLoading } from 'element-plus'
import type { LoadingOptions } from 'element-plus'

/**
 * 立即使用全局 loading,并返回控制对象
 */
export const useGlobalLoading = (text: string = '加载中...', options: Partial<LoadingOptions> = {}) => {
  const loadingInstance = ElLoading.service({
    lock: true,
    text,
    background: 'rgba(255, 255, 255, 0.6)',
    ...options,
  })

  return {
    /** 手动关闭 */
    close: () => loadingInstance.close(),
  }
}

/**
 * 自动 loading 包裹器:执行传入异步函数,并自动显示/关闭 loading
 */
export async function withGlobalLoading<T>(fn: () => Promise<T>, text = '加载中...') {
  const loading = useGlobalLoading(text)
  try {
    const res = await fn()
    return res
  } finally {
    loading.close()
  }
}

这里有 两种方式进行使用 一种是 使用的 普通方式 第二种是Promise

时间格式化

本 hooks 是结合 dayjs 将时间进行格式化 含时区矫正

import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'

// 安装插件(只需一次)
dayjs.extend(utc)
dayjs.extend(timezone)
/**
 * 转换时间格式并将时区改成 东八区
 * @returns
 */
export const useFormatTime = () => {
  const formatTime = (val: string, format = 'YYYY-MM-DD HH:mm:ss') => {
    if (!val) return '--'
    return dayjs.utc(val).tz('Asia/Shanghai').format(format)
  }

  return {
    formatTime,
  }
}

文件上传封装

组件封装 结合 element-plus 进行二次封装

<!-- AvatarUpload.vue -->
<template>
  <el-upload
    class="avatar-uploader"
    :action="uploadUrl"
    :headers="{ Authorization: `Bearer ${token}` }"
    :show-file-list="false"
    :on-success="onSuccess"
    :before-upload="onBeforeUpload">
    <el-image v-if="modelValue" :src="modelValue" class="w-[88px] h-[88px] shadow-md rounded-sm" />
    <iconify-icon v-else icon-name="ep:plus" class="size-4 text-[#8c939d] text-center" />
  </el-upload>
</template>

<script setup lang="ts">
import store from '@/utils/store'
import { ElMessage, type UploadProps } from 'element-plus'
defineProps<{ modelValue: string }>()
const emit = defineEmits(['update:modelValue'])
// 获取 token
const token = computed(() => {
  return store.get('login_token').token
})
// 请求地址
const uploadUrl = 'http://127.0.0.1:8900/api/upload-image' // 可传入 props

// 上传成功后的 回调
const onSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
  if (response.type === 'success') {
    ElMessage.success('图片上传成功')

    emit('update:modelValue', response?.data[0].url)
  }
}
// 上传前的回调
const onBeforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
  if (!allowedTypes.includes(rawFile.type)) {
    ElMessage.error('头像必须是 jpg/png/gif/webp 格式的图片!')
    return false
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error('最大 2MB 图片')
    return false
  }
  return true
}
</script>
<style>
.avatar-uploader .el-upload {
  width: 88px;
  height: 88px;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}
</style>

接口规范 RESTful 风格

操作方法地址示例参数方式
查询列表GET/user/listquery params
新增用户POST/user/addbody
编辑用户PUT/user/:uidbody + params
删除用户DELETE/user/:uidparams

mongodb 建模关系

结构表示的关系类型示例说明
toc: Object一对一(One-to-One)单个 toc 对象,结构平铺
toc: [Object]✅ 一对多(One-to-Many)多个 toc 项构成一个数组
toc: [ObjectId]一对多,引用关系每项是外键引用,通常关联其他表