跳过到内容
+

Crud

Crud 组件提供了与来自任何数据源的数据进行交互的 UI。

使用 Crud 组件及其子组件,您可以轻松生成页面,在这些页面中,可以表格形式列出数据源中的项目,单独显示详细信息,或者通过表单创建和编辑。所有这些都只需通过单个数据源定义进行最少的配置。

演示

Crud 组件自动为您的数据源生成 CRUD 页面,并自动与您的路由解决方案集成。所有需要的只是 dataSource 定义和 CRUD 页面的 rootPath

Enter 开始编辑

页面位于以下路由中

  • 列表: /${rootPath}
  • 显示: /${rootPath}/:id
  • 创建: /${rootPath}/new
  • 编辑: /${rootPath}/:id/edit

这些默认路径和其他开箱即用的设置可以通过遵循下面的高级配置来覆盖和更详细地配置。

建议包含 dataSourceCache prop,以便正确缓存来自数据源查询方法的结果。请参阅下面关于数据缓存的章节了解更多信息。

可选地,可以提供其他配置选项,例如项目分页列表的 initialPageSize,或者在使用表单创建新项目时设置初始表单值的 defaultValues

数据源

数据源是一个具有特定形状的对象,必须用于配置 Crud 组件或其子组件。它包括

  • 一个 fields 属性,它扩展了 Data Grid 列定义,您可以在其中为您的数据指定不同的字段、标题名称和字段类型等。必须有一个 id 字段(字符串或数字),以便可以识别单个项目。

  • 用于与数据交互的方法的属性,例如 getManygetOnecreateOneupdateOnedeleteOne

  • 一个 validate 函数,用于在创建或编辑数据时进行表单验证,它为每个字段返回验证错误。

这是一个简化的数据源定义示例

const notesDataSource: DataSource<Note> = {
  fields: [
    { field: 'id', headerName: 'ID' },
    { field: 'title', headerName: 'Title' },
    { field: 'text', headerName: 'Text' },
  ],
  getMany: ({ paginationModel }) => {
    const start = paginationModel.page * paginationModel.pageSize;
    const end = start + paginationModel.pageSize;
    const paginatedNotes = notesStore.slice(start, end);

    return {
      items: paginatedNotes,
      itemCount: notesStore.length,
    };
  },
  getOne: (noteId) => {
    return notesStore.find((note) => note.id === noteId) ?? null;
  },
  createOne: (data) => {
    const newNote = { id: notesStore.length + 1, ...data } as Note;

    notesStore = [...notesStore, newNote];

    return newNote;
  },
  updateOne: (noteId, data) => {
    let updatedNote: Note | null = null;

    notesStore = notesStore.map((note) => {
      if (note.id === noteId) {
        updatedNote = { ...note, ...data };
        return updatedNote;
      }
      return note;
    });

    return updatedNote;
  },
  deleteOne: (noteId) => {
    notesStore = notesStore.filter((note) => note.id !== noteId);
  },
  validate: (formValues) => {
    let issues: { message: string; path: [keyof Note] }[] = [];

    if (!formValues.title) {
      issues = [...issues, { message: 'Title is required', path: ['title'] }];
    }
    if (!formValues.text) {
      issues = [...issues, { message: 'Text is required', path: ['text'] }];
    }

    return { issues };
  },
};

getMany

数据源中的 getMany 方法可以用于检索分页、排序和过滤的项目,以便作为列表显示,通常在表格中。

分页、排序和过滤可以与您的数据获取集成,通过 paginationModelfilterModelsortModel 参数。这些参数遵循与 Data Grid 使用的分页排序过滤模型相同的形状。

此方法必须返回一个对象数组,其中包含要显示的项目。

{
  //...
  getMany: async ({ paginationModel, filterModel, sortModel }) => {
    // Fetch data from server
    const data = await fetch('https://my-api.com/data', {
      method: 'GET',
      body: JSON.stringify({
        page: paginationModel.page,
        pageSize: paginationModel.pageSize,
        sortModel,
        filterModel,
      }),
    });

    return data
  },
  // ...
}

getOne

数据源中的 getOne 方法可以用于检索单个特定项目并显示其所有属性。

此方法必须返回一个与要显示的项目相对应的对象。

{
  //...
  getOne: async (id) => {
    // Fetch record from server
    const record = await fetch(`https://my-api.com/data/${id}`, {
      method: 'GET',
    });

    return record;
  },
  // ...
}

createOne

数据源中的 createOne 方法可以用于创建新项目,通常来自一个表单,您可以在其中指定每个属性的值。

此方法必须返回一个与已创建的新项目相对应的对象。

{
  //...
  createOne: async (data) => {
    // Create record in the server
    const record = await fetch('https://my-api.com/data', {
      method: 'POST',
      body: JSON.stringify(data),
    });

    return record;
  },
  // ...
}

updateOne

数据源中的 updateOne 方法可以用于更新现有项目,通常来自一个表单,您可以在其中指定每个属性的值。

此方法必须返回一个与已更新的新项目相对应的对象。

{
  //...
  updateOne: async (id, data) => {
    // Update record in the server
    const record = await fetch(`https://my-api.com/data/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });

    return record;
  },
  // ...
}

deleteOne

数据源中的 deleteOne 方法可以用于删除现有项目。

此方法不需要返回任何内容。

{
  //...
  deleteOne: async (id) => {
    // Delete record in the server
    await fetch(`https://my-api.com/data/${id}`, {
      method: 'DELETE',
    });
  },
  // ...
}

表单验证

可选地,可以在数据源中包含 validate 函数,以便进行表单验证。

此函数遵循 标准模式,因此它接受一个包含给定项目的字段值的对象,并且必须返回每个字段的相应错误,如示例所示

{
  //...
  validate: (formValues) => {
    let issues = [];

    if (!formValues.name) {
      issues = [...issues, { message: 'Name is required', path: ['name'] }];
    }
    if (formValues.age < 18) {
      issues = [...issues, { message: 'Age must be higher than 18', path: ['age'] }];
    }

    return { issues };
  },
  // ...
}

当用户尝试在 Crud 组件内提交表单或更改其任何字段时,此函数会自动针对当前值运行。

与外部模式库集成

validate 函数可以轻松地与任何遵循 标准模式 规范的模式库集成,例如 zod

这是一个使用 zod 的示例

import { z } from 'zod';

const dataSource = {
  // ...
  validate: z.object({
    name: z
      .string({ required_error: 'Name is required' })
      .nonempty('Name is required'),
    age: z
      .number({ required_error: 'Age is required' })
      .min(18, 'Age must be higher than 18'),
  })['~standard'].validate,
  // ...
};

数据缓存

数据源默认缓存获取的数据。这意味着如果用户查询已获取的数据,则不会再次调用 getManygetOne 等查询方法,以避免不必要的服务器调用。

成功调用 createOneupdateOnedeleteOne 等突变方法会自动清除同一数据源中所有查询的缓存。

建议始终包含 dataSourceCache prop,以便在整个应用程序的范围内缓存数据,否则默认情况下缓存仅限于正在使用的组件。每个数据源在整个应用程序中都应该有其自己的单个缓存实例。

可以使用 DataSourceCache 的实例进行缓存,如上面的演示所示。DataSourceCache 是一个简单的内存缓存,它将数据存储在普通对象中。

禁用缓存

要禁用数据源缓存,请将 null 传递给 dataSourceCache prop。

Enter 开始编辑

高级配置

为了获得更大的自定义灵活性,特别是如果您想完全控制 CRUD 页面的放置位置,您可以使用 ListShowCreateEdit 子组件,而不是一体化的 Crud 组件。

Enter 开始编辑

CrudProvider 组件是可选的,但它可以用于轻松地将单个 dataSourcedataSourceCache 作为上下文传递给其中的 CRUD 子组件。或者,这些组件中的每一个都可以将自己的 dataSourcedataSourceCache 作为 props。

List 组件

显示一个 Data Grid,列出数据源中的项目,支持分页、排序和过滤,以及一些有用的控件,例如刷新数据。

如果为 onCreateClickonEditClick 传递了 props,则会显示用于触发这些回调的按钮。

如果数据源包含 deleteOne,则可以直接从其各自的行中删除项目。

Enter 开始编辑

与 Data Grid 集成

dataGrid 插槽和插槽 props 可用于将标准 Data Grid 替换为任何 商业许可版本

Enter 开始编辑

Show 组件

显示从数据源检索到的具有给定 id 的项目的详细信息。

如果为 onEditClick 传递了 prop,则会显示一个用于触发该回调的按钮。

如果数据源包含 deleteOne,则可以直接从此视图中删除项目。

Enter 开始编辑

Create 组件

显示一个表单,用于为数据源创建一个新项目,该表单根据给定的 fields 和字段 type 自动生成。

支持的字段类型为 stringnumberbooleandatedateTimesingleSelect

表单验证与数据源中的 validate 函数自动集成。

Enter 开始编辑

Edit 组件

显示一个表单,用于编辑从数据源检索到的具有给定 id 的项目,类似于 Create 组件。

表单字段会预先填充项目的属性。

Enter 开始编辑

API

请参阅下面的文档,以获取此处提及的组件的所有可用 props 和类的完整参考。