vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue3分页组件与中文化

vue3分页组件与中文化详解

作者:leijmdas

这篇文章主要介绍了vue3分页组件与中文化的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

vue3分页组件与中文化

这段代码实现了一个基于Vue 3和Element Plus的分页组件。

组件支持双向绑定的当前页码(currentPage)和每页条数(pageSize)属性,包含总条数(total)显示和可选每页条数设置,支持页码切换和每页条数变化时触发change事件。

通过el-config-provider配置中文语言环境,组件样式采用flex布局右对齐。

父组件通过v-model绑定分页参数,并在change事件中调用数据获取方法。

import zhCn from "element-plus/es/locale/lang/zh-cn"
import {ref} from 'vue'
const locale = ref(zhCn)
<template>
  <div class="table-footer">
<el-config-provider :locale="locale">

    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :total="total"
      :page-sizes="pageSizes"
      layout="total, sizes, prev, pager, next, jumper"
      @size-change="handleChange"
      @current-change="handleChange"
    />
</el-config-provider>

  </div>
</template>

<script>
export default {
  name: 'Pagination',
  props: {
    /* 当前页,支持 v-model:page */
    currentPage: { type: Number, default: 1 },
    /* 每页条数,支持 v-model:limit */
    pageSize: { type: Number, default: 10 },
    /* 总条数 */
    total: { type: Number, default: 0 },
    /* 可选每页条数 */
    pageSizes: {
      type: Array,
      default: () => [10, 20, 30, 40]
    }
  },
  emits: ['update:currentPage', 'update:pageSize', 'change'],
  computed: {
    currentPage: {
      get()  { return this.currentPage },
      set(v) { this.$emit('update:currentPage', v) }
    },
    pageSize: {
      get()  { return this.pageSize },
      set(v) { this.$emit('update:pageSize', v) }
    }
  },
  methods: {
    handleChange() {
      /* 对外暴露一个 change 事件,参数:{ page, limit } */
      this.$emit('change', { currentPage: this.currentPage, pageSize: this.pageSize })
    }
  }
}
</script>

<style scoped>
.table-footer {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}


</style>
<script setup>

import Pagination from '@/components/Pagination.vue'

const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

// 统一获取数据
function getData() {
  // 这里调用接口 list
  console.log('拉取第', currentPage.value, '页', pageSize.value, '条')
}
</script>

<template>
<div>
   <Pagination
      v-model:currentPage="currentPage"
      v-model:pageSize="pageSize"
      :total="total"
      @change="getData"
    />
  </div>
</template>

这个代码是一个 Vue 3 的组合式函数 (Composable Function),它封装了一些常用的全局方法和状态管理逻辑。

我来分析并优化这段代码:

代码分析

功能

优点

可改进点

优化建议 (TypeScript 版本)

import { reactive, ref, getCurrentInstance, ComponentInternalInstance } from 'vue'
import { useGlobalStore } from "../store"
import type { MessageBox, Message, DictType, ApiType } from '../types' // 假设有这些类型定义

interface PageParams {
  currentPage: number
  pageSize: number
  total: number
}

interface TableData<T = any> {
  list: T[]
}

interface UserInfo {
  // 定义用户信息结构
  [key: string]: any
}

export default function useGlobalUtils() {
  const instance = getCurrentInstance()!
  const globalProp = instance.appContext.config.globalProperties
  const globalStore = useGlobalStore()
  
  // 类型化全局工具
  const getMessage = (): Message => globalProp.$message
  const getMessageBox = (): MessageBox => globalProp.$messageBox
  const getDict = (): DictType => globalProp.$dict
  const getApi = (): ApiType => globalProp.$api
  
  // 用户信息(带错误处理)
  const getUserInfo = (): UserInfo => {
    try {
      return JSON.parse(localStorage.userInfo || '{}')
    } catch (e) {
      console.error('解析用户信息失败:', e)
      return {}
    }
  }

  // 确认对话框
  const confirm = async (prompt = "确认提交此次编辑吗?"): Promise<boolean> => {
    try {
      const isConfirm = await getMessageBox().confirm(prompt, "提示", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
      })
      if (isConfirm) {
        console.log("操作已确认")
      }
      return isConfirm
    } catch (error) {
      console.error('确认对话框错误:', error)
      return false
    }
  }

  // 分页状态
  const page = reactive<PageParams>({
    currentPage: 1,
    pageSize: 10,
    total: 0
  })

  // 表格状态
  const tableState = reactive({
    data: {
      list: []
    } as TableData,
    loading: false,
    itemData: {} as any,
    dialogLoading: false
  })

  // 日志方法
  const log = (...args: any[]) => {
    if (process.env.NODE_ENV !== 'production') {
      console.log(...args)
    }
  }

  return {
    globalStore,
    getApi,
    getMessage,
    getMessageBox,
    getDict,
    confirm,
    log,
    userInfo: getUserInfo(),
    page,
    ...tableState,
    // 或者分开暴露
    // tableData: tableState.data,
    // tableLoading: tableState.loading,
    // itemData: tableState.itemData,
    // dialogLoading: tableState.dialogLoading
  }
}

主要改进点

类型安全

错误处理

代码组织

其他改进

使用建议

在组件中使用:

<script setup lang="ts">
const {
  page,
  tableData,
  confirm,
  getApi
} = useGlobalUtils()

// 使用示例
const handleDelete = async () => {
  if (await confirm('确定删除此项吗?')) {
    // 执行删除操作
  }
}
</script>

建议将这些工具函数按功能拆分到不同的文件中,例如:

考虑将用户信息也使用Pinia管理,而不是直接从localStorage读取

这样的优化将使代码更健壮、更易维护,并且在使用TypeScript时能获得更好的类型提示和错误检查。

JavaScript 版本的重写

以下是使用纯 JavaScript 重写的代码,保持了原有功能并进行了优化:

import { reactive, ref, getCurrentInstance } from 'vue'
import { useGlobalStore } from "../store"

export default function useGlobalUtils() {
  const instance = getCurrentInstance()
  const globalProp = instance.appContext.config.globalProperties
  const globalStore = useGlobalStore()
  
  // 获取全局工具方法
  const getMessage = () => globalProp.$message
  const getMessageBox = () => globalProp.$messageBox
  const getDict = () => globalProp.$dict
  const getApi = () => globalProp.$api
  
  // 安全获取用户信息
  const getUserInfo = () => {
    try {
      return JSON.parse(localStorage.userInfo || '{}')
    } catch (e) {
      console.error('解析用户信息失败:', e)
      return {}
    }
  }

  // 确认对话框封装
  const confirm = async (prompt = "确认提交此次编辑吗?") => {
    try {
      const isConfirm = await getMessageBox().confirm(prompt, "提示", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
      })
      if (isConfirm) {
        console.log("操作已确认")
      }
      return isConfirm
    } catch (error) {
      console.error('确认对话框错误:', error)
      return false
    }
  }

  // 分页状态
  const page = reactive({
    currentPage: 1,
    pageSize: 10,
    total: 0
  })

  // 表格相关状态
  const tableState = reactive({
    data: { list: [] },
    loading: false,
    itemData: {},
    dialogLoading: false
  })

  // 开发环境日志
  const log = (...args) => {
    if (process.env.NODE_ENV !== 'production') {
      console.log(...args)
    }
  }

  return {
    // 全局工具
    globalStore,
    getApi,
    getMessage,
    getMessageBox,
    getDict,
    
    // 方法
    confirm,
    log,
    
    // 状态
    userInfo: getUserInfo(),
    page,
    
    // 表格状态 (可展开或直接暴露)
    tableData: tableState.data,
    tableLoading: tableState.loading,
    itemData: tableState.itemData,
    dialogLoading: tableState.dialogLoading,
    
    // 也可以这样暴露
    // ...tableState
  }
}

使用示例

// 在组件中使用
import useGlobalUtils from './useGlobalUtils'

export default {
  setup() {
    const {
      page,
      tableData,
      confirm,
      getApi,
      log
    } = useGlobalUtils()

    // 获取数据示例
    const fetchData = async () => {
      try {
        tableData.loading = true
        const response = await getApi().get('/data', {
          params: {
            page: page.currentPage,
            size: page.pageSize
          }
        })
        tableData.list = response.data.list
        page.total = response.data.total
      } catch (error) {
        log('获取数据失败:', error)
        getMessage().error('获取数据失败')
      } finally {
        tableData.loading = false
      }
    }

    // 删除确认示例
    const handleDelete = async (id) => {
      if (await confirm('确定删除此项吗?')) {
        try {
          await getApi().delete(`/data/${id}`)
          getMessage().success('删除成功')
          fetchData() // 刷新数据
        } catch (error) {
          log('删除失败:', error)
          getMessage().error('删除失败')
        }
      }
    }

    return {
      page,
      tableData,
      handleDelete,
      fetchData
    }
  }
}

主要特点

  1. 纯 JavaScript 实现:完全使用 ES6+ 语法
  2. 错误处理增强:添加了关键操作的错误捕获

状态管理优化

开发友好

灵活性

这个版本保留了所有原始功能,同时提高了代码的健壮性和可维护性。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文