Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(cn): translate content/docs/portals.md into Chinese #147

Merged
merged 8 commits into from
Apr 12, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions content/docs/portals.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ title: Portals
permalink: docs/portals.html
---

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

```js
ReactDOM.createPortal(child, container)
```

The first argument (`child`) is any [renderable React child](/docs/react-component.html#render), such as an element, string, or fragment. The second argument (`container`) is a DOM element.
第一个参数(`child`)是任何[可渲染的 React 子元素](/docs/react-component.html#render),例如一个元素,字符串或 fragment。第二个参数(`container`)是一个 DOM 元素。

## Usage {#usage}
## 用法 {#usage}

Normally, when you return an element from a component's render method, it's mounted into the DOM as a child of the nearest parent node:
通常来讲,当你从组件的 render 方法返回一个元素时,该元素将被挂载到 DOM 节点中离其最近的父节点:

```js{4,6}
render() {
// React mounts a new div and renders the children into it
// React 挂载了一个新的 div,并且把子元素渲染其中
return (
<div>
{this.props.children}
Expand All @@ -27,34 +27,34 @@ render() {
}
```

However, sometimes it's useful to insert a child into a different location in the DOM:
然而,有时候将子元素插入到 DOM 节点中的不同位置也是有好处的:

```js{6}
render() {
zbc marked this conversation as resolved.
Show resolved Hide resolved
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
zbc marked this conversation as resolved.
Show resolved Hide resolved
// React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
// `domNode` 是一个可以在任何位置的有效 DOM 节点。
return ReactDOM.createPortal(
this.props.children,
domNode
);
}
```

A typical use case for portals is when a parent component has an `overflow: hidden` or `z-index` style, but you need the child to visually "break out" of its container. For example, dialogs, hovercards, and tooltips.
一个 portal 的典型用例是当父组件有 `overflow: hidden` `z-index` 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框:

> Note:
> 注意:
>
> 当在使用 portal 时, 记住[管理键盘焦点](/docs/accessibility.html#programmatically-managing-focus)就变得尤为重要。
>
> When working with portals, remember that [managing keyboard focus](/docs/accessibility.html#programmatically-managing-focus) becomes very important.
>
> For modal dialogs, ensure that everyone can interact with them by following the [WAI-ARIA Modal Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal).
> 对于模态对话框,通过遵循 [WAI-ARIA 模态开发实践](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal),来确保每个人都能够运用它。

[**Try it on CodePen**](https://codepen.io/gaearon/pen/yzMaBd)
[**CodePen 上尝试**](https://codepen.io/gaearon/pen/yzMaBd)

## Event Bubbling Through Portals {#event-bubbling-through-portals}
## 通过 Portal 进行事件冒泡 {#event-bubbling-through-portals}

Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the *React tree* regardless of position in the *DOM tree*.
尽管 portal 可以被放置在 DOM 树中的任何地方,但在任何其他方面,其行为和普通的 React 子节点行为一致。由于 portal 仍存在于 *React 树*, 且与 *DOM 树* 中的位置无关,那么无论其子节点是否是 portal,像 context 这样的功能特性都是不变的。

This includes event bubbling. An event fired from inside a portal will propagate to ancestors in the containing *React tree*, even if those elements are not ancestors in the *DOM tree*. Assuming the following HTML structure:
这包含事件冒泡。一个从 portal 内部触发的事件会一直冒泡至包含 *React 树*的祖先,即便这些元素并不是 *DOM 树* 中的祖先。假设存在如下 HTML 结构:

```html
<html>
Expand All @@ -65,10 +65,10 @@ This includes event bubbling. An event fired from inside a portal will propagate
</html>
```

A `Parent` component in `#app-root` would be able to catch an uncaught, bubbling event from the sibling node `#modal-root`.
在 `#app-root` 里的 `Parent` 组件能够捕获到未被捕获的从兄弟节点 `#modal-root` 冒泡上来的事件。

```js{28-31,42-49,53,61-63,70-71,74}
// These two containers are siblings in the DOM
// 在 DOM 中有两个容器是兄弟级 (siblings
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root');

Expand All @@ -79,14 +79,14 @@ class Modal extends React.Component {
}

componentDidMount() {
// The portal element is inserted in the DOM tree after
// the Modal's children are mounted, meaning that children
// will be mounted on a detached DOM node. If a child
// component requires to be attached to the DOM tree
// immediately when mounted, for example to measure a
zbc marked this conversation as resolved.
Show resolved Hide resolved
// DOM node, or uses 'autoFocus' in a descendant, add
// state to Modal and only render the children when Modal
zbc marked this conversation as resolved.
Show resolved Hide resolved
// is inserted in the DOM tree.
// 在 Modal 的所有子元素被挂载后,
// 这个 portal 元素会被嵌入到 DOM 树中,
// 这意味着子元素将被挂载到一个分离的 DOM 节点中。
// 如果要求子组件在挂载时可以立刻接入 DOM 树,
// 例如衡量一个 DOM 节点,
// 或者在后代节点中使用 ‘autoFocus’,
// 则需添加 state Modal 中,
// 仅当 Modal 被插入 DOM 树中才能渲染子元素。
modalRoot.appendChild(this.el);
}

Expand All @@ -110,9 +110,9 @@ class Parent extends React.Component {
}

handleClick() {
// This will fire when the button in Child is clicked,
zbc marked this conversation as resolved.
Show resolved Hide resolved
// updating Parent's state, even though button
// is not direct descendant in the DOM.
// 当子元素里的按钮被点击时,
// 这个将会被触发更新父元素的 state
// 即使这个按钮在 DOM 中不是直接关联的后代
this.setState(state => ({
clicks: state.clicks + 1
}));
Expand All @@ -137,8 +137,8 @@ class Parent extends React.Component {
}

function Child() {
// The click event on this button will bubble up to parent,
// because there is no 'onClick' attribute defined
// 这个按钮的点击事件会冒泡到父元素
// 因为这里没有定义 'onClick' 属性
return (
<div className="modal">
<button>Click</button>
Expand All @@ -149,6 +149,6 @@ function Child() {
ReactDOM.render(<Parent />, appRoot);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBWpE)
[**CodePen 上尝试**](https://codepen.io/gaearon/pen/jGBWpE)

Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a `<Modal />` component, the parent can capture its events regardless of whether it's implemented using portals.
在父组件里捕获一个来自 portal 冒泡上来的事件,使之能够在开发时具有不完全依赖于 portal 的更为灵活的抽象。例如,如果你在渲染一个 `<Modal />` 组件,无论其是否采用 portal 实现,父组件都能够捕获其事件。