资源模板
资源模板描述了 Dojo 资源如何根据传递的选项与其数据源交互。资源模板是静态定义的,并在整个应用程序中使用,为“资源感知”小部件提供支持。可以使用两种类型的 ResourceTemplate
:标准模板和接受初始化选项的模板。
资源感知小部件决定所需的资源 API,默认情况下,唯一所需的 API 是一个 read
函数,该函数旨在根据请求选项将所有资源数据放入资源数据中。Dojo 资源提供了一个默认模板,该模板旨在与应用程序中已有的数据一起使用,这些数据在使用模板时传递给模板工厂。要创建默认模板,请使用 createResourceTemplate
而不传递模板 API,只传递模板唯一 ID 属性的键。
interface ResourceData {
id: string;
name: string;
}
const template = createResourceTemplate<ResourceData>('id');
模板可以创建为一个工厂,该工厂用于使用状态(如数据集或其他自定义信息)初始化模板。这是使用相同的工厂创建的,
资源控件
ResourceControls
作为所有 ResourceTemplate
API 的第二个参数注入,需要用于从资源存储中获取现有的缓存数据并将项目放入存储中。
export interface ResourceGet<S> {
(request?: ResourceReadRequest<S>): ResourceReadResponse<S>;
}
export interface ResourcePut<S> {
(readResponse: ResourceReadResponse<S>, readRequest: ResourceReadRequest<S>): void;
(findResponse: ResourceFindResponse<S> | undefined, findRequest: ResourceFindRequest<S>): void;
}
export interface ResourceControls<S> {
get: ResourceGet<S>;
put: ResourcePut<S>;
}
read()
ResourceTemplate.read
函数负责获取资源的请求数据,并使用 put
资源控件将其设置在存储中。对数据源没有限制,只要使用 put
资源控件将 ResourceReadResponse
设置在存储中即可。
interface ResourceRead<S> {
(request: ResourceReadRequest<S>, controls: ResourceControls<S>): void | Promise<void>;
}
ResourceReadRequest
包含请求的偏移量、页面大小和查询。query
是一个对象,其键映射到与关联值相关的资源项数据接口的键。
type ResourceQuery<S> = { [P in keyof S]?: any };
interface ResourceReadRequest<S> {
offset: number;
size: number;
query: ResourceQuery<S>;
}
find()
ResourceTemplate.find
函数负责根据查找条件在资源中查找特定项目,并使用 put
资源控件将其设置在存储中。对数据查找方式没有限制,只要使用 put
资源控件将 ResourceFindResponse
设置在存储中即可。
export interface ResourceFind<S> {
(options: ResourceFindRequest<S>, controls: ResourceControls<S>): void | Promise<void>;
}
ResourceFindRequest
包含当前资源 options
、query
、type
和查找请求的 start
索引。query
与 ResourceFindRequest
中使用的 query
对象相同:一个对象,其键映射到与关联值相关的资源项数据接口的键。
type FindType = 'exact' | 'contains' | 'start';
interface ResourceFindRequest<S> {
options: ResourceOptions<S>;
query: ResourceQuery<S>;
start: number;
type: FindType;
}
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';
interface User {
firsName: string;
lastName: string;
username: string;
email: string;
}
type
描述了如何使用查询在资源中查找项目,有三种不同的类型。
contains
(默认)- 请求一个值包含查询项值的项目
exact
- 请求与查询值完全匹配的项目
start
- 请求一个值以查询值为开头的项目
init()
init
函数用于使用 resource
中间件处理使用 template
传递的选项。这些选项在创建模板时定义,并传递所需的选项接口,createResourceTemplate<RESOURCE, INIT>
作为第二个泛型参数。
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';
// only showing the init api
const template = createResourceTemplate<{ foo: string }, { data: { foo: string; }[]; extra: number; }>({
init: (options, controls) {
// the options matches the type passed as the second generic
const { data, extra } = options;
// use the controls to work with the store, for example store the init data
controls.put({ data, total: data.length});
}
});
interface ResourceInitRequest<S> {
id: string;
data: S[];
}
export interface ResourceInit<S, I> {
(request: I & { id: string; }, controls: ResourceControls<S>): void;
}
初始化选项与标准 ResourceControls
一起注入函数,用于初始化资源存储。
默认资源模板
Dojo 资源提供了一个预配置的默认资源模板,它实现了完整的资源模板 API。默认模板旨在与 使用模板时传递给小部件的数据 一起使用,该数据初始化模板的资源存储。内存模板是使用来自 @dojo/framework/core/middleware/resources
的 createResourceTemplate
工厂创建的,不传递任何参数。
MyWidget.tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import { createResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
interface ResourceItem {
value: string;
}
interface MyWidgetProperties {
items: ResourceItem[];
}
const resource = createResourceMiddleware();
const factory = create({ resource }).properties<MyWidgetProperties>();
const template = createResourceTemplate<ResourceItem>();
export default factory(function MyWidget({ id, properties, middleware: { resource } }) {
const { items } = properties();
return <MyResourceAwareWidget resource={resource({ template, initOptions: { id, data: items } } )}>
});
有关更多信息,请参阅 使用资源模板。
自定义资源模板
要将资源连接到自定义数据源(如 RESTful API),可以使用 createResourceTemplate()
工厂。至少需要实现 read
API,而 init
和 find
是可选的。
myResourceTemplate.ts
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';
interface MyResource {
id: string;
name: string;
email: string;
}
export default createResourceTemplate<MyResource>({
read: async (request: ResourceReadRequest, controls: ResourceControls) => {
const { offset, size, query } = request;
// use the request details to fetch the required set of data
const url = `https://my-data-source.com?size=${size}&offset=${offset}&query${JSON.stringify(query)}`;
const response = await fetch(url);
const json = await response.json();
controls.put({ data: json.data, total: json.total }, request);
},
find: (request: ResourceFindRequest, controls: ResourceControls) => {
const { query, options, start, type } = request;
// use the start, query, type and options to find an item from the data-source
const url = `https://my-data-source.com/?start=${start}&type=${type}&find${JSON.stringify(query)}`;
const response = await fetch(url);
const json = await response.json();
controls.put({ item: json.item, index: json.index }, request);
}
});
创建具有初始化选项的资源模板
如果资源模板需要支持自定义初始化,可以使用 createResourceTemplate
。这要求模板具有一个 init
API,该 API 将在创建后端资源时被调用。所需的初始化选项使用工厂函数的第二个泛型进行类型化。
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';
interface MyResource {
id: string;
name: string;
email: string;
}
export default createResourceTemplate<MyResource, { data: MyResource[] }>({
init: (request: { id: string } & { data: MyResource[] }, controls: ResourceControls) => {
const { data } = request;
// adds any data passed with the template to resource store
controls.put(data);
},
read: async (request: ResourceReadRequest, controls: ResourceControls) => {
const { offset, size, query } = request;
// use the request details to fetch the required set of data
const url = `https://my-data-source.com?size=${size}&offset=${offset}&query${JSON.stringify(query)}`;
const response = await fetch(url);
const json = await response.json();
controls.put({ data: json.data, total: json.total }, request);
},
find: (request: ResourceFindRequest, controls: ResourceControls) => {
const { query, options, start, type } = request;
// use the start, query, type and options to find an item from the data-source
const url = `https://my-data-source.com/?start=${start}&type=${type}&find${JSON.stringify(query)}`;
const response = await fetch(url);
const json = await response.json();
controls.put({ item: json.item, index: json.index }, request);
}
});
类型化资源模板
所有资源模板工厂都接受一个泛型,用于对资源数据的形状进行类型化。强烈建议为模板提供类型,以便在将模板传递给小部件时,可以正确推断数据和转换的类型。如前面的示例中所述,类型化资源需要在创建模板时传递资源数据类型接口。
userResourceTemplate.ts
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';
interface User {
firsName: string;
lastName: string;
username: string;
email: string;
}
export default createResourceTemplate<User>({
// the template implementation
});