从 Oracle JET 虚拟 DOM 应用程序中的 REST API 提取数据
简介
此教程演示如何访问 REST 服务,将其集成到 Oracle JavaScript Extension Toolkit (Oracle JET) 虚拟 DOM 应用程序中,以及如何将数据绑定到用户界面中的列表视图。
目标
在本教程中,您将学习如何创建 RESTDataProvider 类的实例。此类表示基于 JSON 的 REST 服务可用的数据。
Prerequisites
- 设置为创建包括 Node.js 安装的 Oracle JET 虚拟 DOM 应用程序的开发环境
- (选项 1)完成本系列上一个学习路径中的最终教程:在 Oracle JET 虚拟 DOM 应用程序中处理选择事件
- (选项 2)如果您尚未完成本系列中的上一学习路径:已下载 jet-virtual-dom-app-temp.zip
任务 1:下载 Starter Virtual DOM 应用程序
如果您继续在上一学习路径中创建的应用程序中工作,请跳过此任务。
-
将
jet-virtual-dom-app-temp.zip重命名为JET-Virtual-DOM-app.zip。将内容提取到JET-Virtual-DOM-app目录。 -
导航到
JET-Virtual-DOM-app目录并恢复 Oracle JET 虚拟 DOM 应用程序。npm install虚拟 DOM 应用程序已就绪可供使用。
任务 2:访问 REST 服务
单击 Apex 链接可查看活动资源端点的 REST 数据。
数据包含具有各种属性的作业的列表。
{
"items": [
{
"id": 1,
"name": "Baseball",
"short_desc": "Equipment we carry for baseball players.",
"image": "css/images/product_images/baseball.jpg"
},
. . .
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 4,
"links": [
{
"rel": "self",
"href": "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/"
},
. . .
]
}
熟悉端点返回的数据和属性。在本教程的后面部分中,创建 RESTDataProvider 实例时,您需要了解这些详细信息。请注意,例如,端点如何返回引用一系列单个活动的 items 属性。
任务 3:创建数据提供程序以提取活动数据
-
导航到
JET-Virtual-DOM-app/src/components/目录并在编辑器中打开ParentContainer1.tsx文件。 -
在
ParentContainer1.tsx文件的开头,导入RESTDataProvider模块,并删除MutableArrayDataProvider模块和store_data.json文件的 import 语句或注释掉这些语句。我们还会导入在以后创建
RESTDataProvider时要使用的useMemo钩子。import { h } from "preact"; . . . // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider"); // import * as storeData from "text!./store_data.json"; import { RESTDataProvider } from "ojs/ojrestdataprovider"; import { useState, useMemo } from "preact/hooks"; . . . -
创建一个
keyattributes变量和一个restServerURLActivities变量,该变量引用活动键属性和 REST 端点,您将该端点传递到下一步将创建的RESTDataProvider实例。let keyAttributes: string = 'id'; // REST endpoint that returns Activity data const restServerURLActivities: string = 'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/'; -
创建一个引用
RESTDataProvider模块的新activityDataProvider变量,并删除或注释掉引用MutableArrayDataProvider模块的现有activityDataProvider变量。我们在
ParentContainer1函数中创建新的activityDataProvider变量并将其包装在useMemo挂钩中,以确保仅当数据提供程序中的数据实际更改时才重新创建数据提供程序实例。const ParentContainer1 = () => { const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({ keyAttributes: keyAttributes, url: restServerURLActivities, transforms: { fetchFirst: { request: async (options) => { const url = new URL(options.url); const { size, offset } = options.fetchParameters; url.searchParams.set("limit", String(size)); url.searchParams.set("offset", String(offset)); return new Request(url.href); }, response: async ({ body }) => { const { items, totalSize, hasMore } = body; return { data: items, totalSize, hasMore }; }, }, }, }), []) . . .注:上面从端点响应主体提取数据和其他属性的
response函数必须返回具有data属性的对象。鉴于我们使用的端点返回一个items属性,我们将在响应函数中将此后一个属性分配给data。 -
保存
ParentContainer1.tsx文件。您的
ParentContainer1.tsx文件应类似于 ParentContainer1-a.tsx.txt 。 -
导航到
JET-Virtual-DOM-app/src/components/Activity目录并在编辑器中打开ActivityContainer.tsx文件。 -
在
ActivityContainer.tsx文件的开头,导入RESTDataProvider模块并注释掉或删除MutableArrayDataProvider模块的 import 语句。import { h, ComponentProps } from "preact"; . . . // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider"); import { RESTDataProvider } from "ojs/ojrestdataprovider"; . . . -
在
Props类型别名中,修改可选的data属性以引用RESTDataProvider类型,而不是先前存在的类型MutableArrayDataProvider<Activity["id"], Activity>。type Props = { data?: RESTDataProvider<Activity["id"], Activity>; // data?: MutableArrayDataProvider<Activity["id"], Activity>; . . . }; -
保存
ActivityContainer.tsx文件。您的
ActivityContainer.tsx文件应类似于 ActivityContainer.tsx.txt 。
任务 4:添加错误处理程序以管理提取数据失败
RESTDataProvider 实例提供了一个错误选项,当尝试提取数据失败时,可以使用该选项调用回调函数。您将在尝试提取活动列表失败的情景中实施此功能。
-
在
JET-Virtual-DOM-app/src/components/目录中的ParentContainer1.tsx文件中,从 Preact 导入useRef挂钩。. . . import { RESTDataProvider } from "ojs/ojrestdataprovider"; import { useState, useMemo, useRef } from "preact/hooks"; . . . -
在引用
RESTDataProvider的activityDataProvider变量中,添加error选项及其调用的回调函数 (fetchErrorHandler) 的引用。const ParentContainer1 = () => { const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({ keyAttributes: keyAttributes, url: restServerURLActivities, error: fetchErrorHandler, transforms: { . . . -
在
activityDataProvider变量之前,添加fetchErrorHandler的代码以及用于确定是否成功提取数据的钩子(useState和useRef)。. . . const ParentContainer1 = () => { const [fetchStatus, setFetchStatus] = useState(true); const fetchError = useRef<string>(); const fetchErrorHandler = (errorDetail: RESTDataProvider.FetchErrorDetail<number, Activity> | RESTDataProvider.FetchResponseErrorDetail<number, Activity>) => { setFetchStatus(false); if (errorDetail.hasOwnProperty('response')) { fetchError.current = `${(errorDetail as RESTDataProvider.FetchResponseErrorDetail<number, Activity>).response.status}`; } else { fetchError.current = (errorDetail as RESTDataProvider.FetchErrorDetail<number, Activity>).error.message; } } const activityDataProvider = new RESTDataProvider<Activity["id"], Activity>({ . . . -
在
ParentContainer1.tsx文件结尾的 return 语句中,添加一个检查,确定在尝试提取数据失败时是显示活动列表还是显示消息。. . . return ( <div> {fetchStatus ? ( <div id="parentContainer1" class="oj-flex oj-flex-init"> <ActivityContainer data={activityDataProvider} onActivityChanged={activityChangedHandler} /> {showActivityItems() && (<ParentContainer2 activity={selectedActivity} />)} {!showActivityItems() && (<h4 class="oj-typography-subheading-sm">Select activity to view items</h4>)} </div>) : (<p>Sorry that we couldn't get your product information right now. Please contact your system administrator.</p> )} </div> ); }; export default ParentContainer1; -
保存
ParentContainer1.tsx文件。您的
ParentContainer1.tsx文件应类似于 ParentContainer1-b.tsx.txt 。
任务 5:创建数据提供程序以提取项数据
使用另一个 RESTDataProvider 实例提取数据子集,即特定活动的项列表。您可以通过提供包含所选活动 ID 的新 URL 来执行此操作。
-
导航到
JET-Virtual-DOM-app/src/components/目录并在编辑器中打开ParentContainer2.tsx文件。 -
在
ParentContainer2.tsx文件的开头,导入RESTDataProvider模块,并删除MutableArrayDataProvider模块和store_data.json文件的 import 语句或注释掉这些语句。还要导入在创建的RESTDataProvider实例中启用过滤功能时将使用的TextFilter接口。import { h } from "preact"; . . . import { RESTDataProvider } from "ojs/ojrestdataprovider"; import { TextFilter } from "ojs/ojdataprovider"; // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider"); // import * as storeData from "text!./store_data.json"; . . . -
在
Item类型别名之后,创建一个baseServiceUrl变量以引用将传递给RESTDataProvider实例的 REST 端点,该端点将在下一步中创建。type Item = { . . . }; const baseServiceUrl = "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/"; -
创建
RESTDataProvider的初始实例,在后续步骤中将该实例传递给useState和useEffectPreact 钩子。const baseServiceUrl = 'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/'; let INIT_DATAPROVIDER = new RESTDataProvider<ActivityItem['id'], ActivityItem>({ keyAttributes: 'id', url: baseServiceUrl, transforms: { fetchFirst: { request: null!, response: (): any => { return { data: [] }; }, }, }, }); -
注释掉或删除预先存在的代码,这些代码创建了一个变量以从
store_data.json文件读取数据并创建了MutableArrayDataProvider的初始实例。// const activityData = JSON.parse(storeData); // let activityItemsArray = activityData[0].items; // // Create data provider instance for the array of activity items for the selected activity // const INIT_DATAPROVIDER = new MutableArrayDataProvider<ActivityItem["id"], ActivityItem>(activityItemsArray, { // keyAttributes: "id", // }) -
在
ParentContainer2函数中,将管理MutableArrayDataProvider实例的现有useEffect挂钩替换为新定义,该定义将为与所选活动 ID 对应的活动项创建RESTDataProvider。此新定义还包括要在活动项name字段上筛选的文本筛选器。const ParentContainer2 = (props: Props) => { . . . useEffect(() => { setactivityItemDP( new RESTDataProvider<ActivityItem["id"], ActivityItem>({ keyAttributes: "id", capabilities: { filter: { textFilter: true, }, }, url: baseServiceUrl + "/" + props.activity?.id + "/items/", textFilterAttributes: ["name"], transforms: { fetchFirst: { request: async (options) => { const url = new URL(options.url); const { size, offset } = options.fetchParameters; url.searchParams.set("limit", String(size)); url.searchParams.set("offset", String(offset)); const filterCriterion = options.fetchParameters .filterCriterion as TextFilter<Item>; const { textFilterAttributes } = options.fetchOptions; if ( filterCriterion && filterCriterion.text && textFilterAttributes ) { const { text } = filterCriterion; textFilterAttributes.forEach((attribute) => { url.searchParams.set(attribute, text); }); } return new Request(url.href); }, response: async ({ body }) => { const { items, totalSize, hasMore } = body; return { data: items, totalSize, hasMore }; }, }, }, }) ); }, [props.activity]); return ( . . . -
保存
ParentContainer2.tsx文件。您的
ParentContainer2.tsx文件应类似于 ParentContainer2.tsx.txt 。 -
导航到
JET-Virtual-DOM-app/src/components/ActivityItem目录并在编辑器中打开ActivityItemContainer.tsx文件。 -
在
ActivityItemContainer.tsx文件的开头,导入RESTDataProvider模块并添加注释或删除MutableArrayDataProvider模块的 import 语句。import { h, ComponentProps } from "preact"; . . . // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider"); import { RESTDataProvider } from "ojs/ojrestdataprovider"; . . . -
在
Props类型别名中,修改data属性以引用RESTDataProvider类型,而不是先前存在的类型MutableArrayDataProvider<Activity["id"], Activity>。type Props = { // data?: MutableArrayDataProvider<ActivityItem["id"], ActivityItem>; data?: RESTDataProvider<ActivityItem['id'], ActivityItem>; selectedActivity: Item | null; onItemChanged: (item: Item) => void; }; -
保存
ActivityItemContainer.tsx文件。您的
ActivityItemContainer.tsx文件应类似于 ActivityItemContainer.tsx.txt 。
任务 6:测试虚拟 DOM 应用程序
-
在终端窗口中,转到
JET-Virtual-DOM-app目录并运行虚拟 DOM 应用程序。npx ojet serve -
在浏览器窗口中,查看虚拟 DOM 应用程序中的动态更改。

-
关闭显示正在运行的虚拟 DOM 应用程序的浏览器窗口或选项卡。
-
在终端窗口中,按 Ctrl+C,如果出现提示,输入
y以退出 Oracle JET 工具批处理作业。 -
在终端窗口中,使用以下附加命令行参数运行虚拟 DOM 应用程序。
npx ojet serve --server-port=8144 --livereload-port=8145在此情况下,虚拟 DOM 应用程序显示以下消息,因为其尝试访问的 REST 服务仅接受
ojet serve命令在默认情况下使用的服务器端口 (8000) 上的请求,因此 RESTDataProvider 尝试从 REST 服务提取失败。Sorry that we couldn't get your product information right now. Please contact your system administrator.
后续步骤
本教程是 CRUD Operations Using a REST Service 模块的一部分。
- 从 Oracle JET 中的 REST API 提取数据
- 创建表单以在 Oracle JET 虚拟 DOM 应用程序中创建数据记录
- 在 Oracle JET 虚拟 DOM 应用程序中更新数据记录
- 删除 Oracle JET 虚拟 DOM 应用程序中的数据记录
您可以返回到虚拟 DOM 学习路径的主页,以访问有关构建虚拟 DOM 应用程序的所有模块。
更多学习资源
通过 docs.oracle.com/learn 浏览其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Fetch data from a REST API in an Oracle JET virtual DOM app
F70672-02