在本章中,我们将探讨如何使用AEM GraphQL API来在外部应用程序中提供体验。
本教程使用一个简单的React应用程序来查询和显示由AEM GraphQL API公开的Adventure内容。 React的使用基本上不重要,任何平台的任何框架都可以编写消耗性外部应用程序。
这是一个多部分教程,假定已完成前面部分中概述的步骤。
本章中的IDE屏幕截图来自 Visual Studio代码
或者,也可以选择安装诸如 GraphQL网络检查器 以查看有关GraphQL查询的更多详细信息。
在本章中,我们将学习如何:
由于本章重点介绍如何开发客户端以通过GraphQL使用内容片段,因此示例 必须下载和设置WKND GraphQL React应用程序源代码 本地机器上。
有关启动React应用程序的详细信息,请参阅 快速设置 章节,但可以遵循简略说明:
如果尚未克隆示例的WKND GraphQL React应用程序,请从 Github.com
$ git clone --branch tutorial/react git@github.com:adobe/aem-guides-wknd-graphql.git
在IDE中打开WKND GraphQL React应用程序
从命令行中,导航到 react-app
文件夹
通过从项目根(即 react-app
文件夹)
$ cd aem-guides-wknd-graphql/react-app
$ npm start
在以下位置查看应用程序 http://localhost:3000/. 示例React应用程序包含两个主要部分:
家庭体验通过查询充当WKND冒险的索引 冒险 AEM中使用GraphQL的内容片段。 在本章中,我们将修改此视图,以支持按活动筛选冒险。
探险详细信息体验使用GraphQL查询特定 冒险 内容片段,并显示更多数据点。
使用浏览器的开发工具和浏览器扩展,如 GraphQL网络检查器 以检查发送到AEM的GraphQL查询及其JSON响应。 此方法可用于监控GraphQL请求和响应,以确保它们得到正确表达,并且其响应符合预期。
从React应用程序发送到AEM的GraphQL查询
从AEM到React应用程序的JSON响应
查询和响应应与GraphiQL IDE中显示的内容相匹配。
在开发过程中,React应用程序配置为通过WebPack开发服务器将HTTP请求代理到AEM。 React应用程序会向 http://localhost:3000
将它们代理到上运行的AEM创作服务 http://localhost:4502
. 查看文件 src/setupProxy.js
和 env.development
以了解详细信息。
在非开发方案中,将配置React应用程序,以直接向AEM发出请求。
在IDE中,打开文件 src/api/useGraphQL.js
.
这是 反应效果挂钩 用于侦听应用程序更改 query
,且发生更改时,会向AEM GraphQL端点发出HTTPPOST请求,并将JSON响应返回到应用程序。
每当React应用程序需要进行GraphQL查询时,都会调用此自定义 useGraphQL(query)
挂接,传入GraphQL以发送到AEM。
此挂接使用 fetch
模块,以发出HTTPPOSTGraphQL请求,但其他模块,如 Apollo GraphQL客户端 的值。
打开 src/components/Adventures.js
在IDE中,该IDE负责主视图的历险列表,并回顾调用 useGraphQL
挂。
此代码设置默认 query
为 allAdventuresQuery
在此文件下定义。
const [query, setQuery] = useState(allAdventuresQuery);
随时 query
变量更改, useGraphQL
将调用挂接,进而对AEM执行GraphQL查询,并将JSON返回到 data
变量,该变量随后用于呈现历险列表。
const { data, errorMessage } = useGraphQL(query);
的 allAdventuresQuery
是文件中定义的常量GraphQL查询,该查询可查询所有Adventure内容片段(不进行任何筛选),并且只返回渲染主页视图所需的数据点。
const allAdventuresQuery = `
{
adventureList {
items {
_path
adventureTitle
adventurePrice
adventureTripLength
adventurePrimaryImage {
... on ImageRef {
_path
mimeType
width
height
}
}
}
}
}
`;
打开 src/components/AdventureDetail.js
, React组件负责显示冒险详细信息体验。 此视图使用特定内容片段的JCR路径作为其唯一ID来请求特定内容片段,并呈现提供的详细信息。
类似于 Adventures.js
,自定义 useGraphQL
React Hook可重新用于对AEM执行GraphQL查询。
内容片段的路径是从组件的 props
顶部用于指定要查询的内容片段。
const contentFragmentPath = props.location.pathname.substring(props.match.url.length);
…并使用 adventureDetailQuery(..)
函数,并传递到 useGraphQL(query)
用于对AEM执行GraphQL查询,并将结果返回给 data
变量。
const { data, errorMessage } = useGraphQL(adventureDetailQuery(contentFragmentPath));
的 adventureDetailQuery(..)
函数只需包装过滤GraphQL查询,该查询使用AEM <modelName>ByPath
用于查询由其JCR路径标识的单个内容片段的语法,并返回呈现冒险详细信息所需的所有指定数据点。
function adventureDetailQuery(_path) {
return `{
adventureByPath (_path: "${_path}") {
item {
_path
adventureTitle
adventureActivity
adventureType
adventurePrice
adventureTripLength
adventureGroupSize
adventureDifficulty
adventurePrice
adventurePrimaryImage {
... on ImageRef {
_path
mimeType
width
height
}
}
adventureDescription {
html
}
adventureItinerary {
html
}
}
}
}
`;
}
接下来,让我们修改React应用程序以执行参数化的GraphQL查询,这些查询通过冒险活动来限制主页视图。
在IDE中,打开文件: src/components/Adventures.js
. 此文件表示主页体验的冒险组件,该组件可查询并显示冒险卡片。
Inspect函数 filterQuery(activity)
,但已准备制定一个GraphQL查询,该查询会按 activity
.
请注意该参数 activity
作为 filter
在 adventureActivity
字段,要求该字段的值与参数的值匹配。
function filterQuery(activity) {
return `
{
adventures (filter: {
adventureActivity: {
_expressions: [
{
value: "${activity}"
}
]
}
}){
items {
_path
adventureTitle
adventurePrice
adventureTripLength
adventurePrimaryImage {
... on ImageRef {
_path
mimeType
width
height
}
}
}
}
}
`;
}
更新React Adventures组件的 return
语句,以添加调用新参数化的按钮 filterQuery(activity)
来提供要列出的冒险。
function Adventures() {
...
return (
<div className="adventures">
{/* Add these three new buttons that set the GraphQL query accordingly */}
{/* The first button uses the default `allAdventuresQuery` */}
<button onClick={() => setQuery(allAdventuresQuery)}>All</button>
{/* The 2nd and 3rd button use the `filterQuery(..)` to filter by activity */}
<button onClick={() => setQuery(filterQuery('Camping'))}>Camping</button>
<button onClick={() => setQuery(filterQuery('Surfing'))}>Surfing</button>
<ul className="adventure-items">
...
)
}
保存更改,然后在Web浏览器中重新加载React应用程序。 三个新按钮显示在顶部,单击它们会自动使用匹配的活动重新查询AEM的冒险内容片段。
尝试为活动添加更多过滤按钮: Rock Climbing
, Cycling
和 Skiing
GraphQL是强类型,因此在查询无效时可能会返回有用的错误消息。 接下来,让我们模拟一个错误的查询,以查看返回的错误消息。
重新打开文件 src/api/useGraphQL.js
. Inspect以下代码片段可查看错误处理:
//useGraphQL.js
.then(({data, errors}) => {
//If there are errors in the response set the error message
if(errors) {
setErrors(mapErrors(errors));
}
//Otherwise if data in the response set the data as the results
if(data) {
setData(data);
}
})
.catch((error) => {
setErrors(error);
});
检查响应,以查看其是否包含 errors
对象。 的 errors
如果GraphQL查询存在问题(例如基于架构的未定义字段),则AEM将发送对象。 如果没有 errors
对象 data
设置并返回。
的 window.fetch
包括 .catch
语句至 捕捉 任何常见错误,如HTTP请求无效或无法与服务器建立连接。
打开文件 src/components/Adventures.js
.
修改 allAdventuresQuery
包含无效属性 adventurePetPolicy
:
/**
* Query for all Adventures
* adventurePetPolicy has been added beneath items
*/
const allAdventuresQuery = `
{
adventureList {
items {
adventurePetPolicy
_path
adventureTitle
adventurePrice
adventureTripLength
adventurePrimaryImage {
... on ImageRef {
_path
mimeType
width
height
}
}
}
}
}
`;
我们知道 adventurePetPolicy
不是Adventure模型的一部分,因此这应会触发错误。
保存更改并返回到浏览器。 您应会看到如下错误消息:
GraphQL API检测到 adventurePetPolicy
在中未定义 AdventureModel
和会返回相应的错误消息。
Inspect来自AEM的响应使用浏览器的开发人员工具查看 errors
JSON对象:
的 errors
对象是详细的,其中包含有关错误查询的位置和错误分类的信息。
返回 Adventures.js
并还原查询更改,以将应用程序恢复到正确状态。
恭喜! 您已成功探索了示例WKND GraphQL React应用程序的代码,并将其更新为使用参数化、过滤GraphQL查询来按活动列出冒险! 您还有机会探索一些基本的错误处理。
在下一章中, 使用片段引用进行高级数据建模 您将了解如何使用片段引用功能在两个不同的内容片段之间创建关系。 您还将了解如何修改GraphQL查询以包含引用模型中的字段。