dojo 龙主logo

资源模板

资源模板描述了 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 包含当前资源 optionsquerytype 和查找请求的 start 索引。queryResourceFindRequest 中使用的 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/resourcescreateResourceTemplate 工厂创建的,不传递任何参数。

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,而 initfind 是可选的。

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
});