Component APIs

children

编辑此页面
import { children } from "solid-js";
import type { JSX, ResolvedChildren } from "solid-js";
function children(fn: () => JSX.Element): () => ResolvedChildren

children 辅助函数用于处理更复杂的 props 交互。 当你不是仅在 JSX 中通过 props.children 一次性传递子组件时,你应该使用 children。 Props 通常以这种方式通过 props.children 的 getter 传入:

const resolved = children(() => props.children)

返回值是一个计算得到已解析子组件的 memo,它会在子组件发生变化时更新。 在某些场景下,使用这个 memo 而不是直接访问 props.children 有一些重要的优势。 底层的问题在于,当你通过 JSX 指定组件的子组件时,Solid 会自动将 props.children 定义为一个属性 getter,这样每当访问 props.children 时就会创建子组件(特别是会创建 DOM)。

这有两个具体的影响:

  1. 如果你多次访问 props.children,子组件(及相关的 DOM)会被多次创建。 如果你想要 DOM 被复制,这很有用(因为 DOM 节点只能出现在一个父元素中),但在许多情况下这会创建冗余的 DOM 节点。 如果你改为多次调用 resolved(),你会重用相同的子组件。

  2. 如果你在跟踪作用域之外访问 props.children(例如在事件处理程序中),那么你会创建永远不会被清理的子组件。 如果你改为调用 resolved(),你会重用已解析的子组件。 你还可以确保子组件在当前组件中被跟踪,而不是在其他跟踪作用域(如另一个组件)中。

此外,children 辅助函数通过调用无参数函数并将数组的数组展平成一个数组来"解析"子组件。 例如,在 JSX 中像 {signal() * 2} 这样指定的子组件在 props.children 中会被包装成一个 getter 函数 () => count() * 2,但在 resolved 中会被求值为一个实际的数字,并正确依赖于 count 信号。

如果给定的 props.children 不是数组(当 JSX 标签只有一个子组件时会出现这种情况),那么 children 辅助函数不会将其规范化为数组。 这种行为很有用,例如当意图是将单个函数作为子组件传递时,可以通过 typeof resolved() === 'function' 来检测。 如果你想要规范化为数组,返回的 memo 有一个 toArray 方法 (1.5 版本新增)

在大多数情况下,如果你只是通过 JSX 将 props.children 传递给另一个组件或元素,你不需要(在某些情况下,也不想)使用 children 辅助函数:

const Wrapper = (props) => {
return <div>{props.children}</div>
}

children 辅助函数的一个重要方面是它会强制创建和解析子组件,因为它会立即访问 props.children。 对于条件渲染来说,这可能是不理想的,例如,当在 <Show> 组件中使用子组件时。 例如,以下代码始终会求值子组件:

const resolved = children(() => props.children)
return <Show when={visible()}>{resolved()}</Show>

要仅在 <Show> 渲染子组件时才求值子组件,你可以将 children 的调用推到 <Show> 内部的组件或函数中,这样只有当 when 条件为真时才会求值其子组件。 另一个不错的解决方法是只在实际需要求值子组件时才将 props.children 传递给 children 辅助函数:

const resolved = children(() => visible() && props.children)
报告此页面问题