# @financial-times/x-interaction 中文文档

规范地址：https://npmcn.com/package/%40financial-times/x-interaction/

版本：21\.2\.3
npm 元数据更新时间：2026-10-26T09:14:53.360Z
中文译文更新时间：2026-11-14T18:41:13.490Z
软件包许可：ISC

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40financial-times/x-interaction
原文对照：https://npmcn.com/package/%40financial-times/x-interaction/?lang=original
项目主页：https://github.com/Financial-Times/x-dash/tree/HEAD/components/x-interaction
源码仓库：https://github.com/Financial-Times/x-dash

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：80.8 kB，19 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：未声明
- Node.js 要求：16\.x \|\| 18\.x \|\| 20\.x
- 运行依赖：2 个
- 首次发布：2018-07-25T17:14:41.291Z
- 最新版本发布：2026-10-26T09:14:52.828Z
- 近 30 天下载量：4978（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：205（近 12 个月 17 个）

## 中文简介

此模块允许您写入响应事件并更改自身数据的 x- dash 组件 .

## 安装

```sh
npm install @financial-times/x-interaction
```

也可以使用：`pnpm add @financial-times/x-interaction`、`yarn add @financial-times/x-interaction`、`bun add @financial-times/x-interaction`

## README

# x 互动

此模块允许您写入响应事件并更改自身数据的 x- dash 组件 .

## 安装

此模块在节点16上得到支持,并在npm上得到分发.

```bash
npm install --save @financial-times/x-interaction
```

`x-interaction` 用于内部 `x-dash` 组件,而不是应用程序的依赖.

## 写入交互式组件

主接口 `x-interaction` 是函数 `withActions`,可以用来包裹普通(即. _无国籍人_x-dash组件.

### 行动

动作是传递给组件的函数,意在用于事件处理器. 每个动作返回 a _状态更新_,它既可以是拟合并到组件属性中的对象,也可以是与组件属性合并的函数 _当前_ 属性,并返回要合并的对象:

```jsx
import {withActions} from '@financial-times/x-interaction';

const greetingActions = withActions({
    actionOne() {
        return {greeting: "world"};
    },

    actionTwo() {
        return ({greeting}) => ({
            greeting: greeting.toUpperCase(),
        });
    },
});

const Greeting = greetingActions(({greeting, actions}) => <div>
    hello {greeting}
    <button onClick={actions.actionOne}>"world"</button>
    <button onClick={actions.actionTwo}>uppercase</button>
</div>);
```

点击第一个按钮会将问候设置为 `"world"`,然后单击第二个按钮,将问候设置到之前的大小写。 从您的动作中返回一个函数是使更新状态依赖于先前状态的唯一方法.

### 同步动作

如果一个动作返回一个承诺(例如如果它是一个) `async` 函数), `x-interaction` 将等待承诺 并使用它决定的值 当国家更新, 并设置属性 `isLoading` 改为 `true` 誓以飞翔的盟誓

```jsx
import {withActions} from '@financial-times/x-interaction';

const greetingActions = withActions({
    async updateGreeting() {
        const repsonse = await fetch('/greeting');
        const {greeting} = await response.json();
        return {greeting};
    },
});

const Greeting = greetingActions(({greeting, actions, isLoading}) => <div>
    hello {greeting}
    <button onClick={actions.updateGreeting} disabled={isLoading}>
        {isLoading ? 'loading greeting...' : 'update greeting'}
    </button>
</div>);
```

### 动作中的属性

如果您需要访问组件的属性 _在此之前_ 返回状态更新,例如如果组件需要将参数发送到一个终点,可以将函数传递到 `withActions` 替换动作对象。 您的功能将随 _初次_ 属性,并返回动作对象:

```jsx
import {withActions} from '@financial-times/x-interaction';

const greetingActions = withActions(({lang}) => ({
    async updateGreeting() {
        const repsonse = await fetch(`/greeting?lang=${lang}`);
        const {greeting} = await response.json();
        return {greeting};
    },
}));

const Greeting = greetingActions(({greeting, actions, isLoading}) => <div>
    hello {greeting}
    <button onClick={actions.updateGreeting} disabled={isLoading}>
        {isLoading ? 'loading greeting...' : 'update greeting'}
    </button>
</div>);
```

_当状态更新时, 这些属性将不会改变_,因此它们不应用于有依赖于先前状态的状态;为此使用状态更新函数.

### 已包装和未包装组件

由于动作与组件是分开的,因此基组件通常可以作为一个静态组件而不用包装. 如果该组件的消费者需要提供自己的行动,这样做是有用的。 建议将包裹组件,基组件,动作作为单独命名的出口输出. 其命名惯例是 `ComponentName`, (中文(简体) ), `BaseComponentName` 财务报告和审定财务报表 `componentNameActions`,例如:

```js
import {withActions} from '@financial-times/x-interaction';

export const greetingActions = withActions({});

export const BaseGreeting = ({greeting, actions}) => <div>
    hello {greeting}
</div>;

export const Greeting = greetingActions(BaseGreeting);
```

### 将服务器上架的标记加水

[水分](https://en.wikipedia.org/wiki/Hydration_\(web_development\)#:~:text=In%20web%20development%2C%20hydration%20or,handlers%20to%20the%20HTML%20elements.):客户端JavaScript将服务器端渲染完成的静态HTML网页转换为动态网页的技术,将事件处理器附加到HTML元素中.

当你有一个 `x-interaction` 组件由服务器提供,您想要附加组件的客户端版本来处理动作,而不是手动渲染组件(这可能会变得不易操作,特别是如果页面上有许多组件实例),您可以拥有 `x-interaction` 为您管理它.

这有三个部分:记录组件、序列化和水分化.

#### 登记该构成部分

要注册您需要拨打的组件 `x-interaction`是因为 `registerComponent` 函数,将组件及其名称作为参数.

```jsx
import {withActions, registerComponent} from '@financial-times/x-interaction';

const greetingActions = withActions({
    actionOne() {
        return {greeting: "world"};
    },

    actionTwo() {
        return ({greeting}) => ({
            greeting: greeting.toUpperCase(),
        });
    },
});

const Greeting = greetingActions(({greeting, actions}) => <div>
    hello {greeting}
    <button onClick={actions.actionOne}>"world"</button>
    <button onClick={actions.actionTwo}>uppercase</button>
</div>);

registerComponent(Greeting, 'Greeting')
```

#### 序列

为确保在客户端以相同的初始数据提供组件,并跟踪提供的所有实例及其识别资料, `x-interaction` 出口a `Serialiser` 课。 你个 _必须_ 每个 HTTP 请求在启动时创建新实例,以响应任意数量 `x-interaction` 组件.

这个案例应该传给每一个 `x-interaction` 作为名为 `serialiser`。这将在发送给客户端的数据("水分数据")中添加组件的属性.

终于,每一次 `x-interaction` 组件,您应当输出水分数据. `x-interaction` 出口a `HydrationData` 组件,将序列器作为财产并制作 `<script>` 包含水分数据的标签,指定给一个全局变量,该变量可由 `x-interaction` 客户端运行时间 。 序列器数据输出后无法再次使用 `HydrationData` 组件.

这是使用 `Serialiser` 财务报告和审定财务报表 `HydrationData` 使用 `Greeting` 我们在前一个步骤中注册的组件.

```js
import express from 'express';
import { Greeting } from './Greeting'
import { Serialiser, HydrationData } from '@financial-times/x-interaction';

const app = express();

app.get('/', (req, res) => {
    const serialiser = new Serialiser();

    res.send(`
        ${Greeting({ serialiser })}
        ${HydrationData({ serialiser })}
    `);
});
```

#### 水分处理

当在服务器侧面渲染时,组件输出一个额外的包裹元素,并带有 `data-x-dash-id` 属性。 此为 `x-interaction` 运行时间以识别序列化数据中的组件,并将正确的实例附加在客户端. 你可以把这个作为 `id` 属性;否则将随机生成标识符.

`x-interaction` 导出一个函数 `hydrate`。这应当呼吁客户方。 它检查页面上的全局序列化数据,使用标识符来查找包装元素,并呼叫 `render` 从你选择的 `x-engine` 客户端运行时间,将组件实例放入包装中.

打电话之前 `hydrate`,必须首先 `import` 任意 `x-interaction` 在页面上显示的组件。 组件在 `x-interaction` 导入时运行时间; 您不需要对导入的组件做任何事情 。 这将确保组件包含在您的客户端捆绑中 。 同样,如果你是服务器侧渲染的组件只是你通过 `withActions`,确保您在输入该组件的同时输入其寄存器.

因为 `hydrate` 期望包装纸在 DOM 中被调用时, 它应该在后面调用 [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)。取决于您的页面结构,在滚动到视图时,将组件水合可能是合适的.

水合组件客户端代码的完整示例 :

```js
import { hydrate } from '@financial-times/x-interaction';
import '@financial-times/x-increment'; // bundle x-increment and register it with x-interaction

document.addEventListener('DOMContentLoaded', () => hydrate());
```

如果基础组件需要不能被序列化的属性,例如函数或其他组件,你可以将这些属性传递给 `hydrate`,只要它们能成为该部分每个实例的同值. 论点 `hydrate` 是对象映射 `x-interaction`含有额外属性的对象的组件的内部名称,以传递给该组件的每个位置。 您可以通过调用访问一个组件的内部名称 `getComponentName`。 。 。 .

比如说, `x-interaction` 支持 a `customSlot` 在按钮中渲染反应元素的属性,但不能序列化。 为了让客户知道这一点 我们可以把它作为额外的水合物

```js
import { hydrate, getComponentName } from '@financial-times/x-interaction';
import Increment from '@financial-times/x-increment';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

document.addEventListener('DOMContentLoaded', () => {
    hydrate({
        [getComponentName(Increment)]: {
            customSlot: <FontAwesomeIcon icon='plus' />
        }
    })
});
```

### 外部触发行动

#### 客户端渲染

当使用客户端运行时间( 如 React) 来渲染 `x-interaction` 组件,您可以通过属性 `actionsRef` 到组件。 这应当是一种功能,在使用该组件时,将参照组件实例的行动 `null` 当取出. 这和React类似 [`ref` 属性](https://reactjs.org/docs/refs-and-the-dom.html) 用于获取 DOM 元素的引用.

你可以从应用程序的任何地方调用这些动作引用, 并且它们会被放大到从你得到的引用的组件实例。 这允许外部事件,比如来自不是以x-dash为单位的组件,或者您不控制的第三方组件,触发您组件的状态变化. 也可以使用此功能来触发组件的初始化逻辑,例如当其被滚动到视图时.

这里有一个例子 触发一个 `x-increment` 组件的 `increment` 从组件外的按钮中操作 :

```jsx
import { h, Component } from '@financial-times/x-engine';
import { Increment } from '@financial-times/x-increment';

class ExternalActionDemo extends Component {
    render() {
        return <div>
            <button onClick={() => this.incrementActions && this.incrementActions.increment()}>
                Increment externally
            </button>

            <Increment count={1} actionsRef={actions => this.incrementActions = actions} />
        </div>;
    }
}
```

#### 服务器侧渲染

当您的组件由 [`x-interaction` 客户端水合](https://npmcn.com/package/%40financial-times/x-interaction/#readme-hydrating-server-rendered-markup),无法访问组件实例,所以不能使用 `actionsRef`在此情况下, `x-interaction` 支持通过 a 启动动作 [DOM 自定义事件](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)。 。 。 .

这个活动叫做 `x-interaction.trigger-action`,并应当在您想要触发动作的组件实例的包装元件上发出。 包装有属性 `data-x-dash-id`,可以在选择器中使用,但由于随机生成的默认值 `id` 无法预测,你应该使组件 一个独特的,静态的 `id`。在服务器侧:

```js
res.send(`
    ${Increment({count: 1, id: 'x-interaction-1'})}
    ${getInteractionData()}
`);
```

而客户端:

```js
const wrapper = document.querySelector('[data-x-dash-id="x-interaction-1"]');
```

在那个 `detail` 事件参数,包括属性 `action`,这是触发动作的名称。 您也可以指定属性 `args`,它应该是一个阵列,它将被传递给行动作为其论据:

```js
wrapper.dispatchEvent(
    new CustomEvent(
        'x-interaction.trigger-action',
        { detail: { action: 'increment', args: [ { amount: 5 } ] } }
    )
);
```

## 常见问题

### @financial-times/x-interaction 是什么？

此模块允许您写入响应事件并更改自身数据的 x- dash 组件 \.

### 如何安装 @financial-times/x-interaction？

在项目目录运行 npm install @financial-times/x-interaction，或使用 pnpm add / yarn add / bun add。

### @financial-times/x-interaction 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/financial-times\_\_x-interaction 是否存在。

### @financial-times/x-interaction 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @financial-times/x-interaction 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js 16\.x \|\| 18\.x \|\| 20\.x。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @financial-times/x-interaction 可以商用吗？

@financial-times/x-interaction 使用 ISC 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @financial-times/x-interaction 的下载量有多少？

根据 npm 官方下载统计，@financial-times/x-interaction 在 2026/10/15 – 2026/11/13 这 30 天内被下载 4,978 次，日均约 166 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @financial-times/x-interaction 还在维护吗？

最新版本 21\.2\.3 发布于 2026/10/26（19 天前）；至今共发布 205 个版本，其中过去 12 个月发布了 17 个；首次发布于 2018/07/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

