elementui 导出csv-Vue3这样写页面更快更高效

2023-09-01 0 4,692 百度已收录

前言

在开发和管理后台的过程中,肯定会遇到很多增删改查的页面,而那些页面的逻辑大多是相同的,比如获取列表数据、分页等基本功能,和过滤功能。 区别在于所呈现的数据项。 还有一些操作按钮。

20221203192923

当一开始只有1、2个页面时,大多数开发者可能会直接复制上一个页面的代码,而随着项目的进展,类似页面的数量可能会增加,这直接导致项目代码耦合度越来越高。

这也是项目中应该抽取一些可复用的功能或者组件的主要原因之一

下面,我们封装了一个通用的useList,适配大多数增删改查列表页面elementui 导出csv,让你更快更高效的完成任务,准时上班~

20221203195440岗位知识包

我们需要提取一些通用的参数和函数,并将它们封装到一个通用的钩子中。 以后在其他页面复用相同的功能会更简单、更方便。

定义列表页面的基本分页数据

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

如何获取列表数据

想一想,让useList函数接收一个listRequestFn参数来请求列表中的数据。

定义一个列表变量来存储网络请求的数据内容。 由于内部很难直接确定列表数据类型,因此以形参的形式对外提供列表数据类型。

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

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

设置加载状态

调用外部传入的函数,将获取到的数据参数放入list和total中

关闭加载状态

这里使用了 async/await 语法。 如果请求或者解构出现错误,就会使用catch代码块,然后关闭加载状态。

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

export default function useList<ItemType extends Object>(
  listRequestFn: Function
{
  // 忽略其他代码
  // 数据
  const list = ref([]);
  // 过滤数据
  // 获取列表数据
  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函数窃听数据,当curPage和pageSize的值发生变化时,调用loadData函数获取新数据。

elementui 导出csv-Vue3这样写页面更快更高效

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

现已实现基本列表数据获取

实施数据过滤器

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

通常,我在 ref 中定义过滤条件数组,然后在请求时将 ref 扔给请求函数。

useList函数中,第二个参数接收一个filterOption对象,该对象对应列表中的过滤条件数组。

调整loadData函数,在request函数中传入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类型,否则会失去响应能力,功能无法正常工作

清除过滤器阵列

页面上有一个重置按钮,用于清除过滤条件。 这种重复动作可以通过重置功能来处理。

elementui 导出csv-Vue3这样写页面更快更高效

使用Reflect将所有值设置为undefined,并再次请求数据。

什么是反射? 查看这篇文章反射映射对象[2]

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对象参数,用于执行指定的钩子函数,并在函数成功或失败时输出消息内容。

定义选项类型

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
{
  // ...
}
复制代码

设置选项默认值

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
{
  // ...
}
复制代码

在没有delivery hook的情况下,建议设置默认显示错误信息

优化loadData、exportFile函数

基于elementui封装消息方法

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" });
}
复制代码

加载数据函数

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;
  }
};
复制代码

导出文件函数

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 用法



<el-collapse-item title="筛选条件" name="1">




<el-input
v-model="filterOption.name"
placeholder="筛选指定签名名称"
/>




<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"
/>




筛选
重置









{{ scope.row.name }}




{{ scope.row.mobile || "未绑定手机号码" }}




{{ scope.row.email || "未绑定邮箱地址" }}





<el-button type="primary" link @click="detail(scope.row)"
>详情</el-button
>



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]"
/>



import { UserInfoApi } from "@/network/api/User";
import useList from "@/lib/hooks/useList/index";
const filterOption = ref({});
const {
list,
loading,
reset,
filter,
curPage,
pageSize,
reload,
total,
loadData,
} = useList(
UserInfoApi.list,
filterOption
);

复制代码

本文useList的完整代码位于github.com/QC2168/snippets/tree/main/useList

如果你对这个hook有更好的建议,欢迎PR或者在评论区留言。

另外,为了在日常开发中节省查找打包代码片段的时间,提高工作效率(touch time++)elementui 导出csv,仓库还存储了一些第三方打包代码片段,以方便您使用(持续更新~~)

读完两件事后

如果您认为本文内容对您有所启发,我想请您帮我两个小忙:

点击“在看”,让更多人看到此内容(不管你喜不喜欢,你就是流氓-_-)

关注公众号“Vue社区”,每周重点攻克后端笔试重点难点之一。

在公众号后台回复“电子书”即可免费获得27本精选后台电子书!

点击观看支持我,转发更好

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 elementui elementui 导出csv-Vue3这样写页面更快更高效 https://www.wkzy.net/game/186591.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务