@wordpress/interactivity-router 包支持在不重新加载整个页面的情况下从其他页面加载内容。目前仅支持“基于区域”的模式。“客户端侧导航”仍处于实验阶段。
该包定义了一个具有 core/router 命名空间的 Interactivity API store,暴露了用于处理客户端侧导航的状态和两个操作:navigate 和 prefetch。
@wordpress/interactivity-router 包在 WordPress Core v6.5 版本中引入。这意味着此包已捆绑在高于 v6.5 版本的 WordPress Core 中。
用法
该包旨在在交互块的 view.js 文件中动态导入。这样做是为了减少初始页面加载时的 JS 包大小。
/* view.js */
import { store, withSyncEvent } from '@wordpress/interactivity';
// 这是在您的块中通常使用 navigate() 操作的方式。
store( 'my-namespace/myblock', {
actions: {
// 需要使用 withSyncEvent() 实用程序,因为 preventDefault() 需要同步事件访问。
goToPage: withSyncEvent( function* ( e ) {
e.preventDefault();
// 我们动态导入该包以减少初始 JS 包大小。
// 异步操作被定义为生成器,因此必须使用 `yield` 调用 import()。
const { actions } =
yield import( '@wordpress/interactivity-router' );
yield actions.navigate( e.target.href );
} ),
},
} );
现在,您可以在块的 view.js 文件中调用 actions.navigate() 以导航到不同的页面,或者将其传递给 data-wp-on--click 属性。
加载后,此包向 core/router store 添加了以下状态和操作:
const { state, actions } = store( 'core/router', {
state: {
url: window.location.href,
// `navigating` 和 `initiator` 也是 store 状态的一部分,
// 但它们由 `navigate()` 写入,而不是在此处声明,
// 因此在第一次导航之前读取均为 `undefined`。
},
actions: {
*navigate(href, options) {...},
prefetch(url, options) {...},
}
})
除了当前 URL 之外,store 的状态还描述了导航本身:是否正在飞行中(state.navigating)以及是谁发起的(state.initiator)。见下文 State。
指令
data-wp-router-region
它定义了在导航时更新的区域。它需要一个唯一的 ID 作为值,并且必须与 data-wp-interactive 一起使用以获得正确的命名空间。路由器区域可以放置在交互区域内的任何位置,包括嵌套的交互元素。
data-wp-router-region 添加到具有 data-wp-interactive 的父元素内的子元素时,始终也在子元素上包含 data-wp-interactive。这是路由器区域正常工作的必要条件。该值可以是带有区域 ID 的字符串,也可以是包含 id 和可选 attachTo 属性的 JSON 对象。
示例:
<div data-wp-interactive="myblock" data-wp-router-region="main-list">
<ul>
<li><a href="/post-1">Post 1</a></li>
<li><a href="/post-2">Post 2</a></li>
<li><a href="/post-3">Post 3</a></li>
</ul>
<a data-wp-on--click="actions.navigate" href="/page/2">Page 2</a>
</div>
attachTo 属性是一个 CSS 选择器,指向应渲染新路由器区域的父元素。这对于可能在初始页面上不存在但在后续页面上存在的区域(如模态框或覆盖层)非常有用。
在页面之间导航时:
- 如果区域存在于当前页面和新页面上,则更新其内容。在这种情况下忽略
attachTo。 - 如果新页面上存在没有
attachTo的区域但当前页面上不存在,则不会将其添加到 DOM 中。 - 如果新页面上存在带有
attachTo的区域但当前页面上不存在,则创建该区域并将其附加到attachTo中指定的父元素。 - 如果当前页面上存在区域但新页面上不存在,则将其从 DOM 中移除。在这种情况下忽略
attachTo。
带有 attachTo 的示例:
<div
data-wp-interactive="myblock"
data-wp-router-region='{ "id": "myblock/overlay", "attachTo": "body" }'
>
I'm in a new region!
</div>
操作
navigate
导航到指定页面。
此函数规范化传递的 href,如有必要则获取页面 HTML,并更新在新页面中内容发生变化的任何交互区域。它还会在浏览器会话历史记录中创建一个新的条目。
参数
navigate( href: string, options: NavigateOptions = {} )
href: 页面href。options: 选项对象。force: 如果为true,则强制重新获取 URL。navigate()始终缓存页面,因此如果之前已导航到该页面,将使用该缓存。默认为false。html: 用作替代请求 URL 获取的 HTML 字符串。replace: 如果为true,则替换浏览器会话历史记录中的当前条目。默认为false。timeout: 导航中止前的时间,以毫秒为单位。默认为10000。loadingAnimation: 是否在导航期间显示动画。默认为true。screenReaderAnnouncement: 是否在导航期间向屏幕阅读器发布公告。默认为true。initiator: 标识谁发起了此导航,只要它在飞行中就会发布到state.initiator。非空字符串按原样使用且始终优先。null会抑制归属,因此state.initiator在整个过程中读取为null。如果省略(默认值),则发起者源自环境指令作用域:调用操作的元素的最近封闭data-wp-router-region的 ID(包括该元素本身),如果没有则为null。任何其他值(空字符串、数字、对象、false)被视为null,并在启用SCRIPT_DEBUG时记录警告;它永远不会回退到推导发起者。
prefetch
预取传入 URL 的页面。该页面会被缓存并可用于导航。
该函数规范化 URL 并在内部存储获取承诺,以避免对进行中的请求触发第二次获取。
参数
prefetch( url: string, options: PrefetchOptions = {} )
url: 页面url。options: 选项对象。force: 如果为true,则强制再次获取 URL。html: 用作替代请求 URL 获取的 HTML 字符串。
状态
所有三个属性都是响应式的,因此在指令或 watch() 回调中读取它们时会订阅其更改。
state.url(string):与当前 URL 同步。state.navigating(boolean | undefined): 在客户端导航进行中时,该值为真。导航一旦进入客户端管道即发布开始信号,无需等待目标页面;结束信号在新内容提交到 DOM 后的后续帧中发布,且提交与结束之间的延迟是不确定的。如果导航在半途中回退到完整的页面加载,它会在浏览器替换文档期间保持为真值,并在 10 秒后文档仍然存在时重置为false;如果导航在渲染过程中抛出异常,则正常结束,此时页面可能仅部分更新。在这两种情况下,结束信号均不承诺有新内容。loadingAnimation和screenReaderAnnouncement选项均不影响此键:它们改变的是内置反馈,而非此键。state.initiator(string | null | undefined): 标识谁启动了正在进行的导航——该值解析自navigate()的initiator选项,或者当导航没有可识别的发起者时为null,例如后退/前进遍历、使用无指令范围发出的调用,以及从响应state.navigating、state.initiator或state.url的watch()内部发出的调用(此类调用不会继承其响应的导航的发起者)。导航的结束不会清除它:它保留该导航的值,直到下一次导航开始,或者直到执行重新加载文档的后退/前进遍历将其清除为null。
由于在注册 store 时未声明 navigating 和 initiator,因此在首次客户端导航写入它们之前,两者读取均为 undefined,并且在路由器模块从未加载的页面上也是如此。请通过真值性来使用它们——例如 if ( state.navigating ) 和 state.initiator === myRegionId——而不是与 false 或 null 进行比较。请注意,像 data-wp-bind--aria-busy="state.navigating" 这样的绑定,当值为 undefined 时根本不会渲染任何属性,而不是 aria-busy="false"。
派生的 state.initiator 携带区域的 id,而不是原始的 data-wp-router-region 属性文本。对于 JSON 对象形式,它是 id 属性的值,会剥离 namespace:: 前缀,空或非字符串的 id 读取为 null 而非空字符串。请与赋予该区域的 id 进行对比,拼写需完全一致。
有关完整语义——包括涵盖哪些导航、哪些完全不产生过渡、重叠导航对两者的影响,以及从哪个指令读取它们——请参阅客户端导航指南中的响应导航生命周期。
安装
安装模块:
npm install @wordpress/interactivity-router --save
如果您在 WordPress 之外使用 Interactivity API,则只需要此步骤。
在 WordPress 内部,该包已捆绑在 Core 中。为确保其被排队加载,请将 @wordpress/interactivity-router 添加到脚本模块的依赖数组中。通常可以使用 wp-scripts 等工具自动完成此过程。
此外,此包假设您的代码将在 ES2015+ 环境中运行。如果您使用的环境对这些语言特性和 API 的支持有限或完全不支持,您应该在代码中包含 @wordpress/babel-preset-default 随附的 polyfill。
许可证
作为 Gutenberg 和 WordPress 项目一部分的 Interactivity API 提案是自由软件,并根据 GNU 通用公共许可证第 2 版或(根据您的选择)任何更高版本的条款发布。有关完整许可证信息,请参阅 LICENSE.md。