# 过渡、焦点与窗口

协调应用间的视觉变化、保留焦点并将运行中的应用移动到另一窗口。

本页介绍 WU Framework `4.0.0`。升级现有项目之前，请阅读 [Framework 4.0 与 CLI 1.2 迁移指南](/zh-cn/docs/guides/releases/)。


也可以体验[移动中的应用](/zh-cn/labs/interaction/)：React 编辑器、Vue 收件箱、窗口与 PiP、类型化传递、过渡和 keep-alive。[场景指南](/zh-cn/docs/guides/interactive-workspace/)介绍了如何将其用于你的应用。

<span id="animar-una-actualización"></span>

<span class="section-anchor" id="section-1"></span>

## 为更新添加动画

`wu.transition(mutate, options)` 测量带有 `data-wu-vt` 的元素在变化前后的位置。返回 `ready`、`updateCallbackDone`、`finished`、`skipTransition()` 和 `mode`。通过等待 `updateCallbackDone` 捕获变更错误；`ready` 和 `finished` 始终正常完成。默认模式在 Shadow DOM 中使用 FLIP 与 Web Animations，并遵循减少动态效果偏好。

```js
import { wu } from 'wu-framework';

const root = document.querySelector('#panel');
const item = document.createElement('div');
item.dataset.wuVt = 'product-42';
item.textContent = 'Product 42';
root.append(item);
const transition = wu.transition(() => {
  item.style.transform = 'translateX(80px)';
}, { root, duration: 250 });
await transition.updateCallbackDone;
await transition.finished;
```

运行代码前创建 `#panel`。Vue 应在变更函数内等待 `nextTick()`，Svelte 应等待 `tick()`。React 可用 `wuReact.createWuViewTransition(React)` 和 `wuReact.createUseWuTransition(React)` 协调渲染提交。`mode: "native-document"` 需要显式启用，不保证捕获所有 shadow root 的内部内容。

`wu.transition.between(fromApp, toApp, key, mutate?, options?)` 使用相同的 `data-wu-vt` 键在应用间添加元素动画。可用 `null` 表示宿主，并支持 `fromRoot`/`toRoot`、`duration`、`timeout`、`easing`、`fade` 和 `ghost`。返回相同的 Promise 契约；视觉动画不会传输业务状态。

<span id="foco-accesible-y-keep-alive"></span>

<span class="section-anchor" id="section-2"></span>

## 无障碍焦点与保活

`wu.focus.remember(name, root)` 记录深层焦点，`restore(name)` 恢复焦点，二者均返回布尔值。`forget(name)` 删除记录。`trap(root, { initial, restore })` 为对话框返回清理函数。`describe(element, { labelledBy, describedBy })` 连接跨根标签，并返回实际采用的方式：元素引用、ID 或文本；文本是快照，标签变化时需要更新。

隐藏 `keepAlive` 应用会保留其实例。适配器会检测可用的 React Activity、Vue scope 暂停和 Angular 视图分离/挂接 API。这不会自动停止定时器、socket 或请求；请通过 `wu:app:deactivated` 与 `wu:app:activated` 暂停和恢复，并在卸载时移除监听器。

<span id="mover-una-app-viva-a-otra-ventana"></span>

<span class="section-anchor" id="section-3"></span>

## 将运行中的应用移到另一窗口

```js
import { wu } from 'wu-framework/core';
import 'wu-framework/windows';

// Run after the host has mounted the editor app.
document.querySelector('#detach-editor').addEventListener('click', async () => {
  try {
    const mode = 'documentPictureInPicture' in window ? 'pip' : 'popup';
    await wu.detach('editor', { window: mode, width: 900, height: 700 });
  } catch (error) {
    document.querySelector('#window-status').textContent = error.message;
  }
});
document.querySelector('#attach-editor').addEventListener('click', () => {
  wu.attach('editor');
});
```

在宿主中创建按钮与 `#window-status`。`detach()` 要求应用已挂载且可见，打开窗口需要用户手势。它移动相同的 DOM 节点，代码仍在原窗口执行。通过 `ownerDocument.defaultView` 获取显示窗口。支持弹窗、可用时的画中画或同源 `Window`。

`isDetached(name)` 查询状态；`windowOf(name)` 返回 `Window | null`；`windowsReady()` 加载子系统。关闭窗口、隐藏或卸载应用会将其移回宿主。应处理 `WU_APP_NOT_MOUNTED`、`WU_APP_HIDDEN`、`WU_WINDOW_UNAVAILABLE`、`WU_WINDOW_DENIED` 和 `WU_DETACH_ABORTED`。渲染器需要响应时，可在容器上监听 `wu:app:detached` 与 `wu:app:attached`。