likes
comments
collection
share

Vue3 Composition API 组合函数实现CRUD操作

作者站长头像
站长
· 阅读数 41

在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。当构建前端应用时,我们常常需要复用公共任务的逻辑。这里使用vue组合函数实现一个通用的crud功能

实现如下:函数名为useCRUD,它接收一个名为apis的对象参数,这个对象中包含了一系列用于执行CRUD操作的异步API方法(如pageFunccreateFuncupdateFuncdelFunc)。此函数主要目的是封装与数据管理相关的状态和方法,以便在组件中轻松实现数据的增删改查功能。

具体功能如下:

  1. 初始化状态变量:

    • searchForm:使用ref创建一个响应式对象,用于存储搜索表单的条件。
    • page:同样使用ref创建,表示分页信息,包括每页大小(pageSize)、当前页码(pageNo)和总记录数(total)。
    • tableLoading:也是一个ref对象,用来控制表格加载状态,true表示正在加载数据,false表示加载完成。
    • tableData:存放查询结果的数组,初始化为空数组。
  2. 定义操作方法:

    • reset:重置搜索条件和分页信息,并重新查询第一页数据。
    • queryPage:通过useDebounceFn进行防抖处理,延时300毫秒后执行sendRequest函数以发起查询请求。这样可以避免用户频繁输入搜索条件时立即发送请求,提高性能。
  3. 异步请求逻辑:

    • sendRequest:实际发起HTTP请求的方法,根据当前分页信息和搜索条件调用apis.pageFunc获取数据,并更新tableLoading状态以及pagetableData的数据。
  4. 表单编辑功能:

    • formVisible:一个布尔值ref,表示表单编辑界面是否可见。
    • formData:保存表单编辑内容的响应式对象。
    • showForm:显示表单编辑界面并填充数据的方法,传入需要编辑或新建的项。
    • saveData:处理表单提交事件,根据表单数据中的ID决定是调用apis.updateFunc还是apis.createFunc来执行更新或新增操作,完成后隐藏表单界面。
    • deleteData:删除指定ID的数据,通过调用apis.delFunc实现。

最后,函数返回一组包含了上述所有状态和方法的对象,这些可以直接在组件内部解构赋值,方便在组件中实现对数据的CRUD操作。

use-crud.js 代码如下

import { ref } from 'vue';
import { useDebounceFn } from '@vueuse/core';


export default function useCRUD(apis) {
  // 搜索表单 
  const searchForm = ref({});
  // 分页信息
  const page = ref({
    pageSize: 10,
    pageNo: 1,
    total: 0,
  });
  // 表格加载loading
  const tableLoading = ref(false);
  // 表格数据
  const tableData = ref([]);

  // 重置查询
  const reset = () => {
    page.value.pageNo = 1;
    searchForm.value = {};
    queryPage();
  };

  // 分页查询 加了防抖
  const queryPage = useDebounceFn(() => {
    sendPageRequest();
  }, 300);

  /**
   * 发送分页查询请求
   */
  async function sendPageRequest() {
    tableLoading.value = true;
    const data = await apis.pageFunc({ ...page.value, ...searchForm.value });
    tableLoading.value = false;
  
    if (data) {
      page.value.total = data.total ? data.total : 0;
      tableData.value = data.list ? data.list : [];
    }
  }

  // 编辑or新增-表单弹窗标识
  const formVisible = ref(false);
  // 表单数据
  const formData = ref({});
  // 显示表单弹窗
  function showForm(item) {
    formData.value = { ...item };
    formVisible.value = true;
  }

  /**
   * 保存数据 or 更新数据
   */
  async function saveData() {
    if (formData.value.id) {
      await apis.updateFunc(formData.value);
    } else {
      await apis.createFunc(formData.value);
    }
    formVisible.value = false;
  }
  /**
   * 删除数据
   */
  async function deleteData(id) {
    await apis.delFunc(id);
  }
  // 导出变量 方法
  return {
    searchForm,
    tableLoading,
    page,
    tableData,
    formData,
    reset,
    queryPage,
    formVisible,
    showForm,
    saveData,
    deleteData,
  };
}

举例 use-crud在 user-list.vue 中的使用

<template>
  <div>
    <a-form layout="inline" :model="searchForm">
      <a-form-item label="关键字">
        <a-input style="width: 300px" v-model:value="searchForm.searchWord" placeholder="searchWord" />
      </a-form-item>
      <a-form-item>
        <a-button type="primary" @click="reset"> 查询 </a-button>
        <a-button @click="reset"> 重置 </a-button>
      </a-form-item>
    </a-form>
    <a-table size="small" :pagination="false" :loading="tableLoading" :scroll="{ x: 1300 }" bordered :dataSource="tableData" :columns="userColumns">
      <template #bodyCell="{ column, record }">
        <template v-if="column.dataIndex === 'action'">
          <div>
            <a-button @click="showForm(record)" size="small" type="link">编辑</a-button>
            <a-popconfirm title="你确定要删除吗?" ok-text="确定" cancel-text="取消" @confirm="deleteData(record.id)">
              <a-button size="small" danger type="link">删除</a-button>
            </a-popconfirm>
          </div>
        </template>
      </template>
    </a-table>
    <a-pagination
      showSizeChanger
      showQuickJumper
      show-less-items
      :pageSizeOptions="['5', '10', '20', '30', '50', '100', '200']"
      :defaultPageSize="page.pageSize"
      v-model:current="page.pageNo"
      v-model:pageSize="page.pageSize"
      :total="page.total"
      @change="queryPage"
      @showSizeChange="queryPage"
      :show-total="(total) => `共${total}条`"
    />
    <EditForm v-model="formVisible" v-model:formData="formData" @close="formVisible = false" @save="saveData" />
  </div>
</template>

<script setup>
  import EditForm from './edit-form.vue';
  import { ref } from 'vue';
  import { userApi } from '../api/user-api.js';
  // 这里导入 use-curd.js
  import useCRUD from '../lib/use-curd.js';
  const userColumns = ref([
    {
      title: '用户ID',
      dataIndex: 'id',
      minWidth: 180,
      ellipsis: true,
    },
    {
      title: '名称',
      dataIndex: 'name',
      minWidth: 170,
      ellipsis: true,
    },
    {
      title: '操作',
      dataIndex: 'action',
      fixed: 'right',
      width: 140,
    },
  ]);
  // 这里使用 useCRUD
  const { searchForm, tableLoading, page, tableData, formData, reset, queryPage, formVisible, showForm, saveData, deleteData } = useCRUD({
    pageFunc: userApi.getUserPage,
    createFunc: userApi.getUserPage,
    updateFunc: userApi.getUserList,
    delFunc: userApi.getUserPage,
  });
</script>

转载自:https://juejin.cn/post/7344967859054018623
评论
请登录