vue3分页组件与中文化详解

 更新时间:2025年09月13日 09:42:12   作者: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),它封装了一些常用的全局方法和状态管理逻辑。

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

代码分析

功能

  • 获取全局属性 ($message, $messageBox, $dict, $api)
  • 提供全局状态管理 (Pinia store)
  • 封装了常用方法 (确认对话框、日志等)
  • 提供了分页和表格相关的响应式状态

优点

  • 使用组合式API封装可复用逻辑
  • 集中管理常用工具方法
  • 提供了表格和分页的通用状态

可改进点

  • 类型安全(TypeScript)
  • 错误处理
  • 代码组织
  • 响应式状态初始化

优化建议 (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
  }
}

主要改进点

类型安全

  • 添加了TypeScript类型定义
  • 为全局工具方法添加了返回类型

错误处理

  • 添加了JSON解析的错误处理
  • 确认对话框添加了try-catch

代码组织

  • 将表格相关状态合并到一个reactive对象中
  • 使用更清晰的命名

其他改进

  • 生产环境日志控制
  • 更合理的函数命名
  • 更好的代码注释

使用建议

在组件中使用:

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

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

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

  • useGlobalTools.ts (全局工具)
  • useTableState.ts (表格状态)
  • usePagination.ts (分页逻辑)

考虑将用户信息也使用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. 错误处理增强:添加了关键操作的错误捕获

状态管理优化

  • 使用 reactiveref 管理响应式状态
  • 将相关状态组合在一起

开发友好

  • 生产环境自动禁用日志
  • 清晰的函数命名

灵活性

  • 可以展开或单独暴露表格状态
  • 易于在不同组件中复用

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

总结

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

相关文章

  • 如何设置Vue全局公共方法

    如何设置Vue全局公共方法

    这篇文章主要介绍了如何设置Vue全局公共方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 详解vue-cli 接口代理配置

    详解vue-cli 接口代理配置

    本篇主要介绍了vue-cli 接口代理配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 聊聊vue集成sweetalert2提示组件的问题

    聊聊vue集成sweetalert2提示组件的问题

    这篇文章主要介绍了vue 集成 sweetalert2 提示组件的问题,本文通过项目案例实例代码相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-11-11
  • JS 函数的 call、apply 及 bind 超详细方法

    JS 函数的 call、apply 及 bind 超详细方法

    这篇文章主要描述JS 函数的 call、apply 及 bind 方法的超详细解说,感兴趣的朋友可以参考下文,希望能帮助到您
    2021-08-08
  • Vue3对比Vue2的优点总结

    Vue3对比Vue2的优点总结

    vue3解决了vue2的一些缺陷与弊端,学习新的技术是很有必要的,本文总结了一些vue3的优点,希望各位能尽快转入vue3的使用中
    2021-06-06
  • 浅谈vue中改elementUI默认样式引发的static与assets的区别

    浅谈vue中改elementUI默认样式引发的static与assets的区别

    下面小编就为大家分享一篇浅谈vue中改elementUI默认样式引发的static 与assets的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • Vue.js自定义指令的用法与实例解析

    Vue.js自定义指令的用法与实例解析

    自定义指令是用来操作DOM的。自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM操作,并且是可复用的。这篇文章主要介绍了Vue.js自定义指令的用法与实例解析,一起看看吧
    2017-01-01
  • vue中设置滚动条方式

    vue中设置滚动条方式

    这篇文章主要介绍了在vue中设置滚动条的方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • vue点击按钮实现让页面的某一个元素全屏展示

    vue点击按钮实现让页面的某一个元素全屏展示

    这篇文章主要介绍了vue点击按钮实现让页面的某一个元素全屏展示,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • vue.js路由跳转详解

    vue.js路由跳转详解

    这篇文章主要为大家详细介绍了vue.js路由跳转的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08

最新评论