我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vue3如何写列表页让性能更好

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vue3如何写列表页让性能更好

这篇文章主要讲解了“Vue3如何写列表页让性能更好”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue3如何写列表页让性能更好”吧!

在开发管理后台过程中,一定会遇到不少了增删改查页面,而这些页面的逻辑大多都是相同的,如获取列表数据,分页,筛选功能这些基本功能。而不同的是呈现出来的数据项。还有一些操作按钮。

Vue3如何写列表页让性能更好

对于刚开始只有 1,2 个页面的时候大多数开发者可能会直接将之前的页面代码再拷贝多一份出来,而随着项目的推进类似页面数量可能会越来越多,这直接导致项目代码耦合度越来越高。

这也是为什么在项目中一些可复用的函数或组件要抽离出来的主要原因之一

前置知识

  • Vue

  • Vue Composition Api

封装

我们需要将一些通用的参数和函数抽离出来,封装成一个通用hook,后续在其他页面复用相同功能更加简单方便。

定义列表页面必不可少的分页数据

export default function useList() {  // 加载态  const loading = ref(false);  // 当前页  const curPage = ref(1);  // 总数量  const total = ref(0);  // 分页大小  const pageSize = ref(10);}

如何获取列表数据

思考一番,让useList函数接收一个listRequestFn参数,用于请求列表中的数据。

定义一个list变量,用于存放网络请求回来的数据内容,由于在内部无法直接确定列表数据类型,通过泛型的方式让外部提供列表数据类型。

export default function useList<ItemType extends Object>(  listRequestFn: Function) {  // 忽略其他代码  const list = ref<ItemType[]>([]);}

useList中创建一个loadData函数,用于调用获取数据函数,该函数接收一个参数用于获取指定页数的数据(可选,默认为curPage的值)。

  • 执行流程

  1. 设置加载状态

  2. 调用外部传入的函数,将获取到的数据赋值到listtotal

  3. 关闭加载态

这里使用了 async/await 语法,假设请求出错、解构出错情况会走 catch 代码块,再关闭加载态

这里需要注意,传入的 listRequestFn 函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整

export default function useList<ItemType extends Object>(  listRequestFn: Function) {  // 忽略其他代码  // 数据  const list = ref<ItemType[]>([]);  // 过滤数据  // 获取列表数据  const loadData = async (page = curPage.value) => {    // 设置加载中    loading.value = true;    try {      const {        data,        meta: { total: count },      } = await listRequestFn(pageSize.value, page);      list.value = data;      total.value = count;    } catch (error) {      console.log("请求出错了", "error");    } finally {      // 关闭加载中      loading.value = false;    }  };}

别忘了,还有切换分页要处理

使用 watch 函数监听数据,当curPagepageSize的值发生改变时调用loadData函数获取新的数据。

export default function useList<ItemType extends Object>(  listRequestFn: Function) {  // 忽略其他代码  // 监听分页数据改变  watch([curPage, pageSize], () => {    loadData(curPage.value);  });}

现在实现了基本的列表数据获取

实现数据筛选器

在庞大的数据列表中,数据筛选是必不可少的功能

通常,我会将筛选条件字段定义在一个ref中,在请求时将ref丢到请求函数即可。

在 useList 函数中,第二个参数接收一个filterOption对象,对应列表中的筛选条件字段。

调整一下loadData函数,在请求函数中传入filterOption对象即可

注意,传入的 listRequestFn 函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整

export default function useList<  ItemType extends Object,  FilterOption extends Object>(listRequestFn: Function, filterOption: Ref<Object>) {  const loadData = async (page = curPage.value) => {    // 设置加载中    loading.value = true;    try {      const {        data,        meta: { total: count },      } = await listRequestFn(pageSize.value, page, filterOption.value);      list.value = data;      total.value = count;    } catch (error) {      console.log("请求出错了", "error");    } finally {      // 关闭加载中      loading.value = false;    }  };}

注意,这里 filterOption 参数类型需要的是 ref 类型,否则会丢失响应式 无法正常工作

清空筛选器字段

在页面中,有一个重置的按钮,用于清空筛选条件。这个重复的动作可以交给 reset 函数处理。

通过使用 Reflect 将所有值设定为undefined,再重新请求一次数据。

什么是 Reflect?看看这一篇文章Reflect 映射对象

export default function useList<  ItemType extends Object,  FilterOption extends Object>(listRequestFn: Function, filterOption: Ref<Object>) {  const reset = () => {    if (!filterOption.value) return;    const keys = Reflect.ownKeys(filterOption.value);    filterOption.value = {} as FilterOption;    keys.forEach((key) => {      Reflect.set(filterOption.value!, key, undefined);    });    loadData();  };}

导出功能

除了对数据的查看,有些界面还需要有导出数据功能(例如导出 csv,excel 文件),我们也把导出功能写到useList

通常,导出功能是调用后端提供的导出Api获取一个文件下载地址,和loadData函数类似,从外部获取exportRequestFn函数来调用Api

在函数中,新增一个exportFile函数调用它。

export default function useList<  ItemType extends Object,  FilterOption extends Object>(  listRequestFn: Function,  filterOption: Ref<Object>,  exportRequestFn?: Function) {  // 忽略其他代码  const exportFile = async () => {    if (!exportRequestFn) {      throw new Error("当前没有提供exportRequestFn函数");    }    if (typeof exportRequestFn !== "function") {      throw new Error("exportRequestFn必须是一个函数");    }    try {      const {        data: { link },      } = await exportRequestFn(filterOption.value);      window.open(link);    } catch (error) {      console.log("导出失败", "error");    }  };}

注意,传入的 exportRequestFn 函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整

优化

现在,整个useList已经满足了页面上的需求了,拥有了获取数据,筛选数据,导出数据,分页功能

还有一些细节方面,在上面所有代码中的try..catch中的catch代码片段并没有做任何的处理,只是简单的console.log一下

提供钩子

useList新增一个 Options 对象参数,用于函数成功、失败时执行指定钩子函数与输出消息内容。

定义 Options 类型

export interface MessageType {  GET_DATA_IF_FAILED?: string;  GET_DATA_IF_SUCCEED?: string;  EXPORT_DATA_IF_FAILED?: string;  EXPORT_DATA_IF_SUCCEED?: string;}export interface OptionsType {  requestError?: () => void;  requestSuccess?: () => void;  message: MessageType;}export default function useList<  ItemType extends Object,  FilterOption extends Object>(  listRequestFn: Function,  filterOption: Ref<Object>,  exportRequestFn?: Function,  options? :OptionsType) {  // ...}

设置Options默认值

const DEFAULT_MESSAGE = {  GET_DATA_IF_FAILED: "获取列表数据失败",  EXPORT_DATA_IF_FAILED: "导出数据失败",};const DEFAULT_OPTIONS: OptionsType = {  message: DEFAULT_MESSAGE,};export default function useList<  ItemType extends Object,  FilterOption extends Object>(  listRequestFn: Function,  filterOption: Ref<Object>,  exportRequestFn?: Function,  options = DEFAULT_OPTIONS) {  // ...}

在没有传递钩子的情况霞,推荐设置默认的失败时信息显示

优化loadDataexportFile函数

基于 elementui 封装 message 方法

import { ElMessage, MessageOptions } from "element-plus";export function message(message: string, option?: MessageOptions) {  ElMessage({ message, ...option });}export function warningMessage(message: string, option?: MessageOptions) {  ElMessage({ message, ...option, type: "warning" });}export function errorMessage(message: string, option?: MessageOptions) {  ElMessage({ message, ...option, type: "error" });}export function infoMessage(message: string, option?: MessageOptions) {  ElMessage({ message, ...option, type: "info" });}

loadData 函数

const loadData = async (page = curPage.value) => {  loading.value = true;  try {    const {      data,      meta: { total: count },    } = await listRequestFn(pageSize.value, page, filterOption.value);    list.value = data;    total.value = count;    // 执行成功钩子    options?.message?.GET_DATA_IF_SUCCEED &&      message(options.message.GET_DATA_IF_SUCCEED);    options?.requestSuccess?.();  } catch (error) {    options?.message?.GET_DATA_IF_FAILED &&      errorMessage(options.message.GET_DATA_IF_FAILED);    // 执行失败钩子    options?.requestError?.();  } finally {    loading.value = false;  }};

exportFile 函数

const exportFile = async () => {  if (!exportRequestFn) {    throw new Error("当前没有提供exportRequestFn函数");  }  if (typeof exportRequestFn !== "function") {    throw new Error("exportRequestFn必须是一个函数");  }  try {    const {      data: { link },    } = await exportRequestFn(filterOption.value);    window.open(link);    // 显示信息    options?.message?.EXPORT_DATA_IF_SUCCEED &&      message(options.message.EXPORT_DATA_IF_SUCCEED);    // 执行成功钩子    options?.exportSuccess?.();  } catch (error) {    // 显示信息    options?.message?.EXPORT_DATA_IF_FAILED &&      errorMessage(options.message.EXPORT_DATA_IF_FAILED);    // 执行失败钩子    options?.exportError?.();  }};

useList 使用方法

<template>  <el-collapse>    <el-collapse-item title="筛选条件" name="1">      <el-form label-position="left" label-width="90px" :model="filterOption">        <el-row :gutter="20">          <el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">            <el-form-item label="用户名">              <el-input                v-model="filterOption.name"                placeholder="筛选指定签名名称"              />            </el-form-item>          </el-col>          <el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8">            <el-form-item label="注册时间">              <el-date-picker                v-model="filterOption.timeRange"                type="daterange"                unlink-panels                range-separator="到"                start-placeholder="开始时间"                end-placeholder="结束时间"                format="YYYY-MM-DD HH:mm"                value-format="YYYY-MM-DD HH:mm"              />            </el-form-item>          </el-col>          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">            <el-row class="flex mt-4">              <el-button type="primary" @click="filter">筛选</el-button>              <el-button type="primary" @click="reset">重置</el-button>            </el-row>          </el-col>        </el-row>      </el-form>    </el-collapse-item>  </el-collapse>  <el-table v-loading="loading" :data="list" border style="width: 100%">    <el-table-column label="用户名" min-width="110px">      <template #default="scope">        {{ scope.row.name }}      </template>    </el-table-column>    <el-table-column label="手机号码" min-width="130px">      <template #default="scope">        {{ scope.row.mobile || "未绑定手机号码" }}      </template>    </el-table-column>    <el-table-column label="邮箱地址" min-width="130px">      <template #default="scope">        {{ scope.row.email || "未绑定邮箱地址" }}      </template>    </el-table-column>    <el-table-column prop="createAt" label="注册时间" min-width="220px" />    <el-table-column width="200px" fixed="right" label="操作">      <template #default="scope">        <el-button type="primary" link @click="detail(scope.row)"          >详情</el-button        >      </template>    </el-table-column>  </el-table>  <div v-if="total > 0" class="flex justify-end mt-4">    <el-pagination      v-model:current-page="curPage"      v-model:page-size="pageSize"      background      layout="sizes, prev, pager, next"      :total="total"      :page-sizes="[10, 30, 50]"    />  </div></template><script setup>import { UserInfoApi } from "@/network/api/User";import useList from "@/lib/hooks/useList/index";const filterOption = ref<UserInfoApi.FilterOptionType>({});const {  list,  loading,  reset,  filter,  curPage,  pageSize,  reload,  total,  loadData,} = useList<UserInfoApi.UserInfo[], UserInfoApi.FilterOptionType>(  UserInfoApi.list,  filterOption);</script>

感谢各位的阅读,以上就是“Vue3如何写列表页让性能更好”的内容了,经过本文的学习后,相信大家对Vue3如何写列表页让性能更好这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vue3如何写列表页让性能更好

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue3如何写列表页让性能更好

这篇文章主要讲解了“Vue3如何写列表页让性能更好”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue3如何写列表页让性能更好”吧!在开发管理后台过程中,一定会遇到不少了增删改查页面,而这些
2023-07-04

Vue3这样写列表页,让性能更好更高效!

在开发管理后台过程中,一定会遇到不少了增删改查页面,而这些页面的逻辑大多都是相同的,这样子会导致代码耦合度越来越高,下面,我们将这些可复用的数据抽离出来成hook,既解决耦合度的问题又提高工作效率
2023-05-14

uniapp小程序如何通过虚拟列表配合节流,完成上拉刷新下拉加载,避免页面卡顿,提升性能呢?

本文将介绍uniapp小程序中如何使用虚拟列表和节流两种技术实现上拉刷新下拉加载功能,同时避免因渲染大量数据导致的页面卡顿问题。 一、虚拟列表 在uniapp小程序开发中,当我们需要渲染大量列表数据时,很容易出现页面卡顿现象。这时候,我们可
2023-08-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录