From 91c5ac3c8f7e624f3ad5ed91dcfd297bd1fd8a10 Mon Sep 17 00:00:00 2001 From: Zen Date: Thu, 15 Jul 2021 19:07:40 +0800 Subject: [PATCH] docs(zh-cn): revison doc --- documentation/zh-cn/api.md | 80 +++++++++---------- documentation/zh-cn/comparison.md | 22 ++--- documentation/zh-cn/faq.md | 14 ++-- documentation/zh-cn/guides/getting-started.md | 4 +- documentation/zh-cn/guides/reactivity.md | 6 +- documentation/zh-cn/guides/rendering.md | 38 ++++----- documentation/zh-cn/guides/server.md | 22 ++--- documentation/zh-cn/resources/articles.md | 2 +- documentation/zh-cn/resources/projects.md | 2 +- 9 files changed, 95 insertions(+), 95 deletions(-) diff --git a/documentation/zh-cn/api.md b/documentation/zh-cn/api.md index ea7929bf5..c555b7c66 100644 --- a/documentation/zh-cn/api.md +++ b/documentation/zh-cn/api.md @@ -9,7 +9,7 @@ export function createSignal( ): [get: () => T, set: (v: T) => T]; ``` -这是最基本的响应式 primitive,用于跟踪后续可能变化的单个值。 create 函数返回一对 get 和 set 函数来访问和更新 signal。 +这是最基本的响应式 primitive,用于跟踪后续可能变化的单个值。create 函数返回一对 get 和 set 函数来访问和更新 signal。 ```js const [getValue, setValue] = createSignal(initialValue); @@ -24,9 +24,9 @@ setValue(nextValue); setValue(prev => prev + next); ``` -如果你希望值对更新做出响应,请记住在跟踪范围内访问信号。 跟踪范围是指可以被传递然后计算的函数之内,如 `createEffect` 或 JSX 表达式。 +如果你希望值对更新做出响应,请记住在跟踪范围内访问信号。跟踪范围是指可以被传递然后计算的函数之内,如 `createEffect` 或 JSX 表达式。 -> 如果您希望在 Signal 中存储函数,则必须使用函数的形式: +> 如果你希望在 Signal 中存储函数,则必须使用函数的形式: > > ```js > setValue(() => myFunction); @@ -38,7 +38,7 @@ setValue(prev => prev + next); export function createEffect(fn: (v: T) => T, value?: T, options?: { name?: string }): void; ``` -创建一个新的计算来自动跟踪依赖项并在每次依赖项发生变化导致的渲染之后运行。 非常适合使用 `ref` 或者管理其他副作用。 +创建一个新的计算来自动跟踪依赖项并在每次依赖项发生变化导致的渲染之后运行。非常适合使用 `ref` 或者管理其他副作用。 ```js const [a, setA] = createSignal(initialValue); @@ -47,7 +47,7 @@ const [a, setA] = createSignal(initialValue); createEffect(() => doSideEffect(a())); ``` -effect 函数可以拿到上次执行返回的值。 可以在第二个可选参数设置该值得初始化值。 这可以让我们不用创建额外闭包的情况下就可以进行差异对比。 +effect 函数可以拿到上次执行返回的值。可以在第二个可选参数设置该值得初始化值。这可以让我们不用创建额外闭包的情况下就可以进行差异对比。 ```js createEffect(prev => { @@ -76,7 +76,7 @@ const getValue = createMemo(() => computeExpensiveValue(a(), b())); getValue(); ``` -使用 memo 函数上次执行返回的值调用 memo 函数。 该值可以初始化为可选的第二个参数。 这对于减少计算很有用。 +使用 memo 函数上次执行返回的值调用 memo 函数。该值可以初始化为可选的第二个参数。这对于减少计算很有用。 ```js const sum = createMemo(prev => input() + prev, 0); @@ -109,7 +109,7 @@ export function createResource( ): ResourceReturn; ``` -创建一个可以管理异步请求的 signal。 `fetcher` 是一个异步函数,它接收 `source` 的返回值(如果提供)并返回一个 Promise,其解析值设置在 resource 中。 fetcher 不是响应式的,因此如果希望它运行多次,请传入第一个可选参数。 如果源解析为 false、null 或 undefined,则不会执行获取操作。 +创建一个可以管理异步请求的 signal。`fetcher` 是一个异步函数,它接收 `source` 的返回值(如果提供)并返回一个 Promise,其解析值设置在 resource 中。fetcher 不是响应式的,因此如果希望它运行多次,请传入第一个可选参数。如果源解析为 false、null 或 undefined,则不会执行获取操作。 ```js const [data, { mutate, refetch }] = createResource(getQuery, fetchData); @@ -140,7 +140,7 @@ refetch(); export function onMount(fn: () => void): void; ``` -注册一个在初始话化渲染和元素挂载完成后运行的方法。 非常适合使用 `ref` 或者管理其他的一次性副作用。 它相当于一个没有任何依赖的 `createEffect`。 +注册一个在初始话化渲染和元素挂载完成后运行的方法。非常适合使用 `ref` 或者管理其他的一次性副作用。它相当于一个没有任何依赖的 `createEffect`。 ## `onCleanup` @@ -188,7 +188,7 @@ export function on any> | (() => any), U>( ): (prevValue?: U) => U | undefined; ``` -`on` 主要用来将其传递到计算行为中以使其依赖项更加清晰明了。 如果传递依赖项是数组,则 `input` 和 `prevInput` 也是数组。 +`on` 主要用来将其传递到计算行为中以使其依赖项更加清晰明了。如果传递依赖项是数组,则 `input` 和 `prevInput` 也是数组。 ```js createEffect(on(a, v => console.log(v, b()))); @@ -200,7 +200,7 @@ createEffect(() => { }); ``` -您也可以不用立即执行计算,而是通过将 defer 选项设置为 true 来选择仅在更改时运行计算。 +你也可以不用立即执行计算,而是通过将 defer 选项设置为 true 来选择仅在更改时运行计算。 ```js // 不会立即运行 @@ -217,7 +217,7 @@ export function createRoot(fn: (dispose: () => void) => T): T; 创建一个崭新的,不自动处理的,非跟踪上下文。在嵌套响应式上下文的情况下,如果你不希望在父级重新求值时释放资源这个特性会很有用。这是一种强大的缓存模式。 -所有 Solid 代码都应被 createRoot 包裹,因为它们确保释放所有内存/计算。 通常你不需要担心这个,因为 `createRoot` 被嵌入到所有的 `render` 入口函数中。 +所有 Solid 代码都应被 createRoot 包裹,因为它们确保释放所有内存/计算。通常你不需要担心这个,因为 `createRoot` 被嵌入到所有的 `render` 入口函数中。 ## `mergeProps` @@ -248,7 +248,7 @@ export function splitProps(props: T, ...keys: Array<(keyof T)[]>): [...parts: This is the replacement for destructuring. It splits a reactive object by keys while maintaining reactivity. -这是解构的替代品。 `splitProps` 在保持响应性的同时通过键来拆分响应式对象。 +这是解构的替代品。`splitProps` 在保持响应性的同时通过键来拆分响应式对象。 ```js const [local, others] = splitProps(props, ["children"]); @@ -265,7 +265,7 @@ const [local, others] = splitProps(props, ["children"]); export function useTransition(): [() => boolean, (fn: () => void, cb?: () => void) => void]; ``` -用于在所有异步处理完成后在延迟提交事务中批量异步更新。 这与 Suspense 有所关联,并且仅跟踪在 Suspense 边界下读取的资源。 +用于在所有异步处理完成后在延迟提交事务中批量异步更新。这与 Suspense 有所关联,并且仅跟踪在 Suspense 边界下读取的资源。 ```js const [isPending, start] = useTransition(); @@ -369,7 +369,7 @@ export function createStore( ): [get: Store, set: SetStoreFunction]; ``` -`createStore` 创建一个 Signal 树作为代理,允许独立跟踪嵌套数据结构中的各个值。 create 函数返回一个只读代理对象和一个 setter 函数。 +`createStore` 创建一个 Signal 树作为代理,允许独立跟踪嵌套数据结构中的各个值。create 函数返回一个只读代理对象和一个 setter 函数。 ```js const [state, setState] = createStore(initialValue); @@ -383,7 +383,7 @@ setState({ merge: "thisValue" }); setState("path", "to", "value", newValue); ``` -Store 代理对象仅跟踪访问的属性。并在访问 Store 时递归地生成嵌套数据上的嵌套 Store 对象。但是它只包装数组和普通对象。类不包装。 所以像 `Date`、`HTMLElement`、`Regexp`、`Map`、`Set` 之类的东西都不是响应式粒度的。此外,如果不访问对象上的属性,则无法跟踪顶级状态对象。因此它不适用于迭代对象,因为添加新键或索引无法触发更新。因此,将数组放在键上,而不是尝试使用状态对象本身。 +Store 代理对象仅跟踪访问的属性。并在访问 Store 时递归地生成嵌套数据上的嵌套 Store 对象。但是它只包装数组和普通对象。类不包装。所以像 `Date`、`HTMLElement`、`Regexp`、`Map`、`Set` 之类的东西都不是响应式粒度的。此外,如果不访问对象上的属性,则无法跟踪顶级状态对象。因此它不适用于迭代对象,因为添加新键或索引无法触发更新。因此,将数组放在键上,而不是尝试使用状态对象本身。 ```js // 将列表作为状态对象的键 @@ -569,7 +569,7 @@ export function createMutable( `createMutable` 用于集成外部系统或作为与 MobX/Vue 的兼容层会很有用。 -> **注意:** 由于可变状态可以在任何地方传递和修改,这会使其更难以遵循并且更容易打破单向流,因此通常建议使用 `createStore` 代替。 `produce` 修饰符可以提供许多相同的好处而没有任何缺点。 +> **注意:** 由于可变状态可以在任何地方传递和修改,这会使其更难以遵循并且更容易打破单向流,因此通常建议使用 `createStore` 代替。`produce` 修饰符可以提供许多相同的好处而没有任何缺点。 ```js const state = createMutable(initialValue); @@ -636,7 +636,7 @@ export function CounterProvider(props) { } ``` -传递给 provider 的值按原样传递给 `useContext`。 这意味着包装为响应性的表达式将不起作用。 你应该直接传入 Signal 和 Store,而不是在 JSX 中访问它们。 +传递给 provider 的值按原样传递给 `useContext`。这意味着包装为响应性的表达式将不起作用。你应该直接传入 Signal 和 Store,而不是在 JSX 中访问它们。 ## `useContext` @@ -658,7 +658,7 @@ export function children(fn: () => any): () => any; Used to make it easier to interact with `props.children`. This helper resolves any nested reactivity and returns a memo. Recommended approach to using `props.children` in anything other than passing directly through to JSX. -用于更容易地与`props.children`交互。 这个工具函数解决层级嵌套的响应性并返回一个 Memo。 除了直接传递值给 JSX 这种情况之外,推荐使用 `props.children` 的方法。 +用于更容易地与`props.children`交互。这个工具函数解决层级嵌套的响应性并返回一个 Memo。除了直接传递值给 JSX 这种情况之外,推荐使用 `props.children` 的方法。 ```js const list = children(() => props.children); @@ -687,7 +687,7 @@ const ComponentA = lazy(() => import("./ComponentA")); # 第二 Primitive -您的第一个 app 可能不需要它们,但这些有用的工具也不可或缺。 +你的第一个 app 可能不需要它们,但这些有用的工具也不可或缺。 ## `createDeferred` @@ -855,14 +855,14 @@ export function pipeToWritable( ): void; ``` -此方法渲染到 Web 流。 它同步渲染内容,包括任何 Suspense 回退占位符,然后在完成时继续从任何异步资源流式传输数据。 +此方法渲染到 Web 流。它同步渲染内容,包括任何 Suspense 回退占位符,然后在完成时继续从任何异步资源流式传输数据。 ```js const { readable, writable } = new TransformStream(); pipeToWritable(App, writable); ``` -`onReady` 选项对于写入围绕核心应用程序渲染的流很有用。 请记住,如果您需要使用 `onReady` 手动调用 `startWriting` +`onReady` 选项对于写入围绕核心应用程序渲染的流很有用。请记住,如果你需要使用 `onReady` 手动调用 `startWriting` ## `isServer` @@ -870,7 +870,7 @@ pipeToWritable(App, writable); export const isServer: boolean; ``` -这指明了代码是在服务器运行还是在浏览器运行。 由于底层运行时将其导出为常量布尔值,所以它允许构建工具从相应的包中消除代码及其使用的导入代码。 +这指明了代码是在服务器运行还是在浏览器运行。由于底层运行时将其导出为常量布尔值,所以它允许构建工具从相应的包中消除代码及其使用的导入代码。 ```js if (isServer) { @@ -881,11 +881,11 @@ if (isServer) { # 控制流 -Solid 使用组件来控制流。原因是为了提高响应式性能,我们必须控制元素的创建方式。 例如,对于列表而言,简单的 `map` 效率低下,因为它总是映射所有内容。 这意味着需要一个辅助函数。 +Solid 使用组件来控制流。原因是为了提高响应式性能,我们必须控制元素的创建方式。例如,对于列表而言,简单的 `map` 效率低下,因为它总是映射所有内容。这意味着需要一个辅助函数。 将这些包装在组件中既能很方便地简化模板,也允许用户组合和构建自己的控制流。 -这些内置的控制流将被自动导入。除了 `Portal` 和 `Dynamic` 之外的所有内容都是从 `solid-js` 导出的。 这两个 DOM 特定的组件由 `solid-js/web` 导出。 +这些内置的控制流将被自动导入。除了 `Portal` 和 `Dynamic` 之外的所有内容都是从 `solid-js` 导出的。这两个 DOM 特定的组件由 `solid-js/web` 导出。 > 注意:控制流的所有回调/渲染函数子项都是非跟踪性的。这允许创建嵌套状态,并更好地隔离响应。 @@ -929,7 +929,7 @@ function Show(props: { }): () => JSX.Element; ``` -Show 控制流用于有条件地渲染视图的一部分。 它跟三元运算符(`a ? b : c`)类似,但非常适合模板 JSX。 +Show 控制流用于有条件地渲染视图的一部分。它跟三元运算符(`a ? b : c`)类似,但非常适合模板 JSX。 ```jsx 0} fallback={
Loading...
}> @@ -1053,7 +1053,7 @@ function SuspenseList(props: { }): JSX.Element; ``` -`SuspenseList` 可以协调多个并行的 `Suspense` 和 `SuspenseList` 组件。 它控制显示内容的顺序以减少布局抖动,并且可以通过选项控制折叠或隐藏回退状态。 +`SuspenseList` 可以协调多个并行的 `Suspense` 和 `SuspenseList` 组件。它控制显示内容的顺序以减少布局抖动,并且可以通过选项控制折叠或隐藏回退状态。 ```jsx @@ -1080,7 +1080,7 @@ function Dynamic( ): () => JSX.Element; ``` -该组件允许您插入任意组件或标签并将 props 传递给它。 +该组件允许你插入任意组件或标签并将 props 传递给它。 ```jsx @@ -1097,9 +1097,9 @@ export function Portal(props: { }): Text; ``` -`` 会在挂载节点中插入元素。 用于在页面布局之外插入模态框。事件仍然通过组件层次结构传播。 +`` 会在挂载节点中插入元素。用于在页面布局之外插入模态框。事件仍然通过组件层次结构传播。 -除非目标是 document head,否则 portal 挂载在`
` 中。 `useShadow` 将元素放在 Shadow Root 中以进行样式隔离,如果插入到 SVG 元素中,则需要 `isSVG` 避免不插入 `
`。 +除非目标是 document head,否则 portal 挂载在`
` 中。`useShadow` 将元素放在 Shadow Root 中以进行样式隔离,如果插入到 SVG 元素中,则需要 `isSVG` 避免不插入 `
`。 ```jsx @@ -1109,9 +1109,9 @@ export function Portal(props: { # 特殊的 JSX 属性 -一般来说,Solid 试图和 DOM 习惯保持一致。 大多数 props 被视为原生元素的属性和 Web Components 的属性,但其中一些具有特殊的行为。 +一般来说,Solid 试图和 DOM 习惯保持一致。大多数 props 被视为原生元素的属性和 Web Components 的属性,但其中一些具有特殊的行为。 -使用 TypeScript 自定义命名空间属性时,您需要扩展 Solid 的 JSX 命名空间: +使用 TypeScript 自定义命名空间属性时,你需要扩展 Solid 的 JSX 命名空间: ```ts declare module "solid-js" { @@ -1137,7 +1137,7 @@ declare module "solid-js" { ## `ref` -Refs 是一种访问 JSX 中底层 DOM 元素的方式。虽然确实可以将一个元素分配给一个变量,但将组件留在 JSX 流中更为理想。 Refs 在渲染时(在元素连接到 DOM 之前)分配。 它有 2 种写法。 +Refs 是一种访问 JSX 中底层 DOM 元素的方式。虽然确实可以将一个元素分配给一个变量,但将组件留在 JSX 流中更为理想。Refs 在渲染时(在元素连接到 DOM 之前)分配。它有 2 种写法。 ```js // 简单赋值 @@ -1151,7 +1151,7 @@ onMount(() => console.log(myDiv));
console.log(el)} /> ``` -Refs 也可以用于组件。 它们仍然需要连接到另一侧。 +Refs 也可以用于组件。它们仍然需要连接到另一侧。 ```jsx function MyComp(props) { @@ -1175,7 +1175,7 @@ function App() { ## `style` -Solid 的样式工具可以处理字符串或对象。 与 React 的版本不同,Solid 在底层使用了 `element.style.setProperty`。这意味着支持 CSS 变量,但也意味着我们使用较底层的、破折号版本的属性。这实际上会带来更好的性能并能 SSR 输出保持一致。 +Solid 的样式工具可以处理字符串或对象。与 React 的版本不同,Solid 在底层使用了 `element.style.setProperty`。这意味着支持 CSS 变量,但也意味着我们使用较底层的、破折号版本的属性。这实际上会带来更好的性能并能 SSR 输出保持一致。 ```jsx // 字符串 @@ -1195,7 +1195,7 @@ Solid 的样式工具可以处理字符串或对象。 与 React 的版本不同 ## `innerHTML`/`textContent` -它们的工作原理与它们的等效属性相同。设置一个字符串,它们将被设置到 HTML 中。 **小心!!** 任何数据设置为 `innerHTML` 都可能暴露给终端用户,因此它可能成为恶意攻击的载体。`textContent` 虽然通常不需要,但实际上是一种性能优化,因为它绕过了通用对比差异例程,因此子项将只是文本。 +它们的工作原理与它们的等效属性相同。设置一个字符串,它们将被设置到 HTML 中。**小心!!** 任何数据设置为 `innerHTML` 都可能暴露给终端用户,因此它可能成为恶意攻击的载体。`textContent` 虽然通常不需要,但实际上是一种性能优化,因为它绕过了通用对比差异例程,因此子项将只是文本。 ```jsx
@@ -1209,7 +1209,7 @@ Solid 中的事件处理程序通常采用 `onclick` 或 `onClick` 形式,具
console.log(e.currentTarget)} /> ``` -Solid 还支持将数组传递给事件处理句柄以将值绑定到事件处理句柄的第一个参数。 这不用使用`bind` 或创建额外的闭包,因此它是一种高度优化的事件委托方式。 +Solid 还支持将数组传递给事件处理句柄以将值绑定到事件处理句柄的第一个参数。这不用使用`bind` 或创建额外的闭包,因此它是一种高度优化的事件委托方式。 ```jsx function handler(itemId, e) { @@ -1221,7 +1221,7 @@ function handler(itemId, e) { ; ``` -事件不能被重新绑定并且绑定不是响应式。原因是添加/移除侦听器通常更消耗性能。由于事件自然地会被调用,因此不需要响应性,如果需要,只需跟下面一样简单处理您的事件句柄。 +事件不能被重新绑定并且绑定不是响应式。原因是添加/移除侦听器通常更消耗性能。由于事件自然地会被调用,因此不需要响应性,如果需要,只需跟下面一样简单处理你的事件句柄。 ```jsx // 如果定义了就会调用,否则不会。 @@ -1238,13 +1238,13 @@ function handler(itemId, e) { ## `use:___` -`use:___` 是自定义指令。 从某种意义上说,这只是 ref 上的语法糖,但允许我们轻松地将多个指令附加到单个元素。 指令只是一个具有以下签名的函数: +`use:___` 是自定义指令。从某种意义上说,这只是 ref 上的语法糖,但允许我们轻松地将多个指令附加到单个元素。指令只是一个具有以下签名的函数: ```ts function directive(element: Element, accessor: () => any): void; ``` -这些函数在渲染时运行,您可以在其中执行任何操作。创建 signal 和 effects,注册清理函数,随心所欲。 +这些函数在渲染时运行,你可以在其中执行任何操作。创建 signal 和 effects,注册清理函数,随心所欲。 ```js const [name, setName] = createSignal(""); @@ -1280,7 +1280,7 @@ declare module "solid-js" { ## `attr:___` -强制将 prop 视为 attribute 而不是 property。 对于要设置 attribute 的 Web 组件很有用。 +强制将 prop 视为 attribute 而不是 property。对于要设置 attribute 的 Web 组件很有用。 ```jsx diff --git a/documentation/zh-cn/comparison.md b/documentation/zh-cn/comparison.md index df404fd58..5c2d18833 100644 --- a/documentation/zh-cn/comparison.md +++ b/documentation/zh-cn/comparison.md @@ -4,9 +4,9 @@ ## React -React 对 Solid 产生了很大的影响。React Hooks API 中的单向数据流和明确的读写分离影响了 Solid 的 API。 Solid 更加像是一个 “渲染库” 而不是一个框架。 Solid 对如何在应用程序开发中管理数据有着独到的看法,但并不试图约束执行。 +React 对 Solid 产生了很大的影响。React Hooks API 中的单向数据流和明确的读写分离影响了 Solid 的 API。Solid 更加像是一个 “渲染库” 而不是一个框架。Solid 对如何在应用程序开发中管理数据有着独到的看法,但并不试图约束执行。 -然而,尽管 Solid 与 React 的设计理念保持一致,但它的底层运作方式完全不同。React 使用 Virtual DOM 而 Solid 没有。 React 的抽象是自上而下的组件分区,其中渲染方法被重复调用和差异对比。 相反,Solid 将每个模板整体渲染一次,构建其响应图,然后才执行与细粒度更改相关的指令。 +然而,尽管 Solid 与 React 的设计理念保持一致,但它的底层运作方式完全不同。React 使用 Virtual DOM 而 Solid 没有。React 的抽象是自上而下的组件分区,其中渲染方法被重复调用和差异对比。相反,Solid 将每个模板整体渲染一次,构建其响应图,然后才执行与细粒度更改相关的指令。 #### 迁移建议: @@ -14,35 +14,35 @@ Solid 的更新模型完全不像 React,甚至不像 React + MobX。不要将 ## Vue -Solid 在设计方面并没有特别受到 Vue 的影响,但它们在方法上来讲是可以进行比较的。他们都在响应式系统中使用 Proxy,并能基于读取的自动跟踪。但这就是所有的相似之处。 Vue 的细粒度依赖检测只是提供给一个细粒度的虚拟 DOM 和组件系统,而 Solid 将其粒度保持在它的直接 DOM 更新上。 +Solid 在设计方面并没有特别受到 Vue 的影响,但它们在方法上来讲是可以进行比较的。他们都在响应式系统中使用 Proxy,并能基于读取的自动跟踪。但这就是所有的相似之处。Vue 的细粒度依赖检测只是提供给一个细粒度的虚拟 DOM 和组件系统,而 Solid 将其粒度保持在它的直接 DOM 更新上。 Vue 重视简单,而 Solid 重视透明度。尽管 Vue 与 Vue 3 的新方向更符合 Solid 所采用的方法。这些库可能会随着时间的推移更加一致,这取决于它们如何继续发展。 #### 迁移建议: -作为另一个现代响应式库的 Vue 3, 迁移起来你应该会感觉很熟悉。 Solid 的组件非常类似于在 Vue 的 `setup` 函数末尾标记模板。 小心地同函数来计算覆盖状态推导。 响应性无处不在。 Solid 的代理有意设置为只读。在你尝试之前不要批评它。 +作为另一个现代响应式库的 Vue 3, 迁移起来你应该会感觉很熟悉。Solid 的组件非常类似于在 Vue 的 `setup` 函数末尾标记模板。小心地同函数来计算覆盖状态推导。响应性无处不在。Solid 的代理有意设置为只读。在你尝试之前不要批评它。 ## Svelte -Svelte 开创了 Solid 在一定程度上也采用的预编译消失型框架。这两个库都是真正的响应式,可以生成非常小的执行代码包,尽管 Svelte 是小型 demo 的赢家。 Solid 需要在其声明中更加明确,更少依赖编译器的隐式分析,但这正是 Solid 卓越性能的一部分。 Solid 还在运行时保留了更多东西,这在更大的应用程序中可以更好地扩展。 Solid 的 RealWorld 演示实现比 Svelte 的小 25%。 +Svelte 开创了 Solid 在一定程度上也采用的预编译消失型框架。这两个库都是真正的响应式,可以生成非常小的执行代码包,尽管 Svelte 是小型 demo 的赢家。Solid 需要在其声明中更加明确,更少依赖编译器的隐式分析,但这正是 Solid 卓越性能的一部分。Solid 还在运行时保留了更多东西,这在更大的应用程序中可以更好地扩展。Solid 的 RealWorld 演示实现比 Svelte 的小 25%。 这两个库都旨在帮助他们的开发人员编写更少的代码,但方法却完全不同。Svelte 3 专注于优化处理本地化更改的易用性,重点是普通对象交互和双向绑定。相比之下,Solid 通过故意采用 CQRS 和不可变接口来专注于数据流。通过功能模板组合,在许多情况下,Solid 允许开发人员编写比 Svelte 更少的代码,尽管 Svelte 的模板语法绝对更简洁。 #### 迁移建议: -开发体验非常不同,虽然有些东西是相似的,但这是一种非常不同的体验。 Solid 中的组件消耗低,所以不要担心拥有更多的组件。 +开发体验非常不同,虽然有些东西是相似的,但这是一种非常不同的体验。Solid 中的组件消耗低,所以不要担心拥有更多的组件。 ## Knockout.js 这个库的存在归功于 Knockout。该项目的动机是将其用于细粒度依赖性检测的模型现代化。Knockout 于 2010 年发布,支持 Microsoft Explorer 回到 IE6,而 Solid 的大部分内容根本不支持 IE。 -Knockout 的绑定只是在运行时遍历的 HTML 中的字符串。它们取决于克隆上下文($parent 等...)。 而 Solid 使用 JSX 或 JavaScript API 的标签模板字面量来模板化。 +Knockout 的绑定只是在运行时遍历的 HTML 中的字符串。它们取决于克隆上下文($parent 等...)。而 Solid 使用 JSX 或 JavaScript API 的标签模板字面量来模板化。 最大的区别可能是 Solid 的批处理更改方法可确保同步性,而 Knockout 具有使用延迟微任务队列的 deferUpdates。 #### 迁移建议: -如果您习惯了 Knockout,Solid 的 primitive 对你来说可能看起来很奇怪。读/写分离是有意的,而不仅仅是为了让生活更艰难。可以采用状态/动作 (Flux) 心智模型。虽然这些库看起来相似,但它们提倡不同的最佳实践。 +如果你习惯了 Knockout,Solid 的 primitive 对你来说可能看起来很奇怪。读/写分离是有意的,而不仅仅是为了让生活更艰难。可以采用状态/动作 (Flux) 心智模型。虽然这些库看起来相似,但它们提倡不同的最佳实践。 ## Lit & LighterHTML @@ -52,15 +52,15 @@ Knockout 的绑定只是在运行时遍历的 HTML 中的字符串。它们取 #### 迁移建议: -这些库非常小,而且很容易在上面构建。但是,请记住,`` 不仅仅是 HTMLElement(数组或函数)。尝试将您的东西保存在 JSX 模板中。提升在大多数情况下都有效,但最好在心理上将其视为渲染库而不是 HTMLElement 工厂。 +这些库非常小,而且很容易在上面构建。但是,请记住,`` 不仅仅是 HTMLElement(数组或函数)。尝试将你的东西保存在 JSX 模板中。提升在大多数情况下都有效,但最好在心理上将其视为渲染库而不是 HTMLElement 工厂。 ## S.js -这个库对 Solid 的反应式设计影响最大。Solid 在内部使用了 S.js 几年,直到特征需求使它们走上了不同的道路。S.js 是迄今为止最高效的响应式库之一。它像数字电路一样对所有同步时间步长进行建模,并确保一致性,而无需执行诸如 MobX 之类的库中的许多更复杂的机制。 Solid 的反应性归根结底是 S 和 MobX 之间的一种混合。这使它比大多数反应式库(Knockout、MobX、Vue)具有更高的性能,同时为开发人员保留了易于使用的心智模型。S.js 最终仍然是性能更高的反应式库,尽管除了最严厉的综合基准测试之外,差异几乎不明显。 +这个库对 Solid 的反应式设计影响最大。Solid 在内部使用了 S.js 几年,直到特征需求使它们走上了不同的道路。S.js 是迄今为止最高效的响应式库之一。它像数字电路一样对所有同步时间步长进行建模,并确保一致性,而无需执行诸如 MobX 之类的库中的许多更复杂的机制。Solid 的反应性归根结底是 S 和 MobX 之间的一种混合。这使它比大多数反应式库(Knockout、MobX、Vue)具有更高的性能,同时为开发人员保留了易于使用的心智模型。S.js 最终仍然是性能更高的反应式库,尽管除了最严厉的综合基准测试之外,差异几乎不明显。 ## RxJS -RxJS 是一个响应式库。虽然 Solid 对 Observable 数据有类似的想法,但它有着许多观察者模式不同的应用。虽然 Signal 就像一个 Observable 的简单版本(只有 next),但自动依赖检测的模式取代了 RxJS 的一百个左右的操作符。 Solid 有能力采用这种方法,事实上,该库的早期版本也包含类似的运算符,但在大多数情况下,在计算中编写自己的转换逻辑更为直接。在 Observable 是冷启动、单播和基于推送的情况下,客户端上的许多情况都是热启动和多播,这也是 Solid 的默认行为。 +RxJS 是一个响应式库。虽然 Solid 对 Observable 数据有类似的想法,但它有着许多观察者模式不同的应用。虽然 Signal 就像一个 Observable 的简单版本(只有 next),但自动依赖检测的模式取代了 RxJS 的一百个左右的操作符。Solid 有能力采用这种方法,事实上,该库的早期版本也包含类似的运算符,但在大多数情况下,在计算中编写自己的转换逻辑更为直接。在 Observable 是冷启动、单播和基于推送的情况下,客户端上的许多情况都是热启动和多播,这也是 Solid 的默认行为。 ## 其他 diff --git a/documentation/zh-cn/faq.md b/documentation/zh-cn/faq.md index 424e13adb..094ed583c 100644 --- a/documentation/zh-cn/faq.md +++ b/documentation/zh-cn/faq.md @@ -2,16 +2,16 @@ ### 1. 没有 VDOM 的 JSX? 这是 [雾件](https://zh.wikipedia.org/wiki/%E9%9C%A7%E4%BB%B6)吗? 我听过像其他框架的作者强调说这是不可能的。 -当你没有 React 的更新模型时,这是可能的。JSX 是一个模板 DSL,就像任何其他的模板一样。只是在某些方面更灵活的一种。插入任意 JavaScript 有时可能具有挑战性,但与支持扩展运算符没有什么不同。 所以不,这不是雾件,而是一种被证明是最高效的方法。 +当你没有 React 的更新模型时,这是可能的。JSX 是一个模板 DSL,就像任何其他的模板一样。只是在某些方面更灵活的一种。插入任意 JavaScript 有时可能具有挑战性,但与支持扩展运算符没有什么不同。所以不,这不是雾件,而是一种被证明是最高效的方法。 -真正的好处在于它的可扩展性。你有编译器为你工作,为您提供最佳的原生 DOM 更新,但您拥有像 React 这样的库的所有自由,可以使用诸如 Render Props 和高阶组件之类的技术以及响应式钩子来编写组件。不喜欢 Solid 的流程控制? 写你自己的。 +真正的好处在于它的可扩展性。你有编译器为你工作,为你提供最佳的原生 DOM 更新,但你拥有像 React 这样的库的所有自由,可以使用诸如 Render Props 和高阶组件之类的技术以及响应式钩子来编写组件。不喜欢 Solid 的流程控制? 写你自己的。 ### 2. Solid 的性能如何? 我希望我只需要指出一件事,但它确实是最重要的许多选择决定的: 1. 显式响应性,因此只跟踪应该反应性的事物。 -2. 编译时考虑到初始创建。 Solid 使用启发式算法来松散粒度以减少计算次数,同时保持关键更新的粒度和性能。 +2. 编译时考虑到初始创建。Solid 使用启发式算法来松散粒度以减少计算次数,同时保持关键更新的粒度和性能。 3. 响应式表达式只是函数。这使得 "消失的组件" 能够通过惰性 props 求值移除不必要的包装器和同步开销。 这些是目前独特的技术组合,使 Solid 在竞争中具有优势。 @@ -20,7 +20,7 @@ 不会。而且可能永远不会有。虽然 API 是相似的,并且组件通常可以通过小的编辑距离策略来移动,但更新模型根本不同。React 组件会一遍又一遍地渲染,因此 Hooks 之外的代码的运行方式非常不同。闭包和钩子规则不仅是不必要的,它们还可以以在 Solid 不起作用的方式使用。 -另一方面,Vue-compat 是可行的。 虽然目前没有实施的计划。 +另一方面,Vue-compat 是可行的。虽然目前没有实施的计划。 ### 4. 为什么解构不起作用?我觉得到我可以通过将整个组件包装在一个函数中来修复它。 @@ -36,7 +36,7 @@ ### 6. 我真的不喜欢 JSX,模板 DSL 有机会吗? 哦,我看到你标记了标签模板字面量/HyperScript。也许我会用那些... -别。我会马上阻止你。我们像 Svelte 使用他们的模板一样使用 JSX 来创建优化的 DOM 指令。标签模板字面量 和 HyperScript 解决方案确实令人印象深刻,但除非您有真正的理由,例如无构建要求,否则它们在各方面都较差。较大的包、较慢的性能以及需要手动解决方法包装值。 +别。我会马上阻止你。我们像 Svelte 使用他们的模板一样使用 JSX 来创建优化的 DOM 指令。标签模板字面量 和 HyperScript 解决方案确实令人印象深刻,但除非你有真正的理由,例如无构建要求,否则它们在各方面都较差。较大的包、较慢的性能以及需要手动解决方法包装值。 有选择是件好事,但 Solid 的 JSX 确实是最好的解决方案。模板 DSL 也很棒,虽然限制更多,但 JSX 为我们免费提供了很多。现有解析器、语法高亮、TypeScript、Prettier、代码完成,以及最后但并非最不重要的 TypeScript。 @@ -46,11 +46,11 @@ 存储自动包装嵌套值,使其成为深层数据结构,是数据模型的理想选择。对于大多数其他情况,Signal 是轻量级的,并且可以出色地完成工作。 -尽管我很想将这些包装在一起作为一个单一的 API,但你不能代理基本数据类型。函数是最简单的接口,任何响应式式表达式(包括状态访问)都可以在传输时包装成一个,如果这提供了一个通用 API。您可以随意命名您的 signal 和状态,并且它保持最小。我想要做的最后一件事是在用户端强制键入 `.get()` `.set()` 或更糟的 `.value`。为了简洁起见,至少前者可以使用别名,而后者只是调用函数的最简单的方法。 +尽管我很想将这些包装在一起作为一个单一的 API,但你不能代理基本数据类型。函数是最简单的接口,任何响应式式表达式(包括状态访问)都可以在传输时包装成一个,如果这提供了一个通用 API。你可以随意命名你的 signal 和状态,并且它保持最小。我想要做的最后一件事是在用户端强制键入 `.get()` `.set()` 或更糟的 `.value`。为了简洁起见,至少前者可以使用别名,而后者只是调用函数的最简单的方法。 ### 8.为什么我不能像在 Vue.js Svelte MobX 中那样为 Solid 的 Store 赋值? 有双向绑定么? -响应性是一种强大的工具,但也是一种危险的工具。 MobX 知道这一点并引入了严格模式和 Action 来限制更新发生的位置/时间。在 Solid 处理整个组件数据树时 ,我意识到我们可以从 React 中学到一些东西。只要您提供拥有相同约定的方法,您就不需要实际上是不可变的数据。 +响应性是一种强大的工具,但也是一种危险的工具。MobX 知道这一点并引入了严格模式和 Action 来限制更新发生的位置/时间。在 Solid 处理整个组件数据树时,我意识到我们可以从 React 中学到一些东西。只要你提供拥有相同约定的方法,你就不需要实际上是不可变的数据。 能够传递更新状态的能力可以说比决定传递状态更重要。因此,能够将其分开很重要,而且只有在读取不可变的情况下才有可能。如果我们仍然可以粒度更新,我们也不需要付出不可变的成本。幸运的是,ImmutableJS 和 Immer 有大量的现有技术。具有讽刺意味的是,Solid 主要用作具有可变内部结构和不可变接口,和 Immer 刚好相反。 diff --git a/documentation/zh-cn/guides/getting-started.md b/documentation/zh-cn/guides/getting-started.md index 9314dd042..e1c9aa1b7 100644 --- a/documentation/zh-cn/guides/getting-started.md +++ b/documentation/zh-cn/guides/getting-started.md @@ -73,7 +73,7 @@ Solid 的设计提出了一些可以帮助我们最好地构建网站和应用 ## Web 组件 -Solid 生而将 Web 组件作为一等公民。随着时间的推移,它的设计不断发展,目标也发生了变化。然而,Solid 仍然是编写 Web 组件的好选择。 [Solid Element](https://github.com/solidjs/solid/tree/main/packages/solid-element) 允许你编写和包装 Solid 的函数组件以生成小型且高性能的 Web 组件。在 Solid 应用程序中,Solid Element 仍然能够利用 Solid 的 Context API,并且 Solid 的 Portals 支持隔离样式的 Shadow DOM 。 +Solid 生而将 Web 组件作为一等公民。随着时间的推移,它的设计不断发展,目标也发生了变化。然而,Solid 仍然是编写 Web 组件的好选择。[Solid Element](https://github.com/solidjs/solid/tree/main/packages/solid-element) 允许你编写和包装 Solid 的函数组件以生成小型且高性能的 Web 组件。在 Solid 应用程序中,Solid Element 仍然能够利用 Solid 的 Context API,并且 Solid 的 Portals 支持隔离样式的 Shadow DOM 。 ## 服务端渲染 @@ -109,4 +109,4 @@ Solid 拥有动态的服务器端渲染解决方案,可实现真正的同构 ``` -请记住,你仍然需要相应的 DOM 表达式库才能配合 TypeScript 使用。 你也可以搭配 [Lit DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/lit-dom-expressions) 使用标签模板字面量或者搭配 [Hyper DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/hyper-dom-expressions) 使用 HyperScript。 +请记住,你仍然需要相应的 DOM 表达式库才能配合 TypeScript 使用。你也可以搭配 [Lit DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/lit-dom-expressions) 使用标签模板字面量或者搭配 [Hyper DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/hyper-dom-expressions) 使用 HyperScript。 diff --git a/documentation/zh-cn/guides/reactivity.md b/documentation/zh-cn/guides/reactivity.md index 651feac09..34144af92 100644 --- a/documentation/zh-cn/guides/reactivity.md +++ b/documentation/zh-cn/guides/reactivity.md @@ -1,6 +1,6 @@ # 响应性 -Solid 的数据管理建立在一系列灵活的响应式 primitives 之上,这些 primitives 负责所有的更新。它采用与 MobX 或 Vue 非常相似的方法,只是它没有和虚拟 DOM 进行颗粒度绑定。当你访问您的 Effects 和 JSX 视图代码中的响应式值时,它会自动跟踪依赖项。 +Solid 的数据管理建立在一系列灵活的响应式 primitive 之上,这些 primitive 负责所有的更新。它采用与 MobX 或 Vue 非常相似的方法,只是它没有和虚拟 DOM 进行颗粒度绑定。当你访问你的 Effects 和 JSX 视图代码中的响应式值时,它会自动跟踪依赖项。 Solid 的 primitives 通常以 `create` 调用的形式出现,通常返回元组,其中通常第一个元素是可读 primitive,第二个元素是 setter。通常通过 primitive 名称来引用可读部分。 @@ -47,7 +47,7 @@ const fullName = createMemo(() => `${firstName()} ${lastName()}`); Signal 作为事件发射器持有订阅列表。每当它们的值发生变化时,它们都会通知其订阅者。 -更有趣的是这些订阅是如何发生的。 Solid 使用自动依赖跟踪。数据一旦变化,更新会自动发生。 +更有趣的是这些订阅是如何发生的。Solid 使用自动依赖跟踪。数据一旦变化,更新会自动发生。 里面利用了运行时的全局堆栈的小技巧来实现。在 Effect 或 Memo 执行(或重新执行)开发人员编写函数之前,它会将自己压入该堆栈。然后读取的任何 Signal 检查堆栈上是否有当前侦听器,如果有,则将该侦听器添加到其订阅中。 @@ -90,6 +90,6 @@ function createSignal(value) { 1. 所有响应性都从函数调用中跟踪的,无论是直接的还是隐藏在 getter/proxy 下通过访问属性触发的。这意味着你在何处访问响应式对象的属性很重要。 -2. 流程控制下的组件和回调函数不会跟踪作用域且只执行一次。这意味着在组件中解构或在顶层处理逻辑将不会触发重新执行。您必须从其他响应式 primitives 或 JSX 中访问这些 Signal、Store 和属性,以便重新运行对应部分代码。 +2. 流程控制下的组件和回调函数不会跟踪作用域且只执行一次。这意味着在组件中解构或在顶层处理逻辑将不会触发重新执行。你必须从其他响应式 primitive 或 JSX 中访问这些 Signal、Store 和属性,以便重新运行对应部分代码。 3. 这种方法只能进行同步跟踪。如果你使用 setTimeout 或在的 Effect 中使用异步函数,那么 Solid 并不会跟踪异步执行的代码。 diff --git a/documentation/zh-cn/guides/rendering.md b/documentation/zh-cn/guides/rendering.md index 9dc547b00..776412089 100644 --- a/documentation/zh-cn/guides/rendering.md +++ b/documentation/zh-cn/guides/rendering.md @@ -1,10 +1,10 @@ # 渲染 -Solid 支持 JSX、标签模板字面量 和 Solid HyperScript 变体这 3 种模板形式。其中 JSX 是主流,这是因为 JSX 是一门优秀的编译型 DSL。 它有着清晰的语法,支持 TypeScript,可与 Babel 配合使用,并支持其他工具,如代码语法高亮和 Prettier。 使用一种基本上免费为您提供所有功能的工具是相当务实的。 JSX 作为一个编译的解决方案,它提供了很好的开发体验。 当你可以使用一门如此广受支持且支持自定义语法的 DSL 时,有什么可纠结的呢? +Solid 支持 JSX、标签模板字面量 和 Solid HyperScript 变体这 3 种模板形式。其中 JSX 是主流,这是因为 JSX 是一门优秀的编译型 DSL。它有着清晰的语法,支持 TypeScript,可与 Babel 配合使用,并支持其他工具,如代码语法高亮和 Prettier。使用一种基本上免费为你提供所有功能的工具是相当务实的。JSX 作为一个编译的解决方案,它提供了很好的开发体验。当你可以使用一门如此广受支持且支持自定义语法的 DSL 时,有什么可纠结的呢? ## JSX 编译 -渲染涉及到将 JSX 模板预编译为优化的原生 js 代码。 JSX 代码会被构造成: +渲染涉及到将 JSX 模板预编译为优化的原生 js 代码。JSX 代码会被构造成: - 在每个实例都会被克隆的模板 DOM 元素 - 仅使用 firstChild 和 nextSibling 的一系列引用声明 @@ -16,21 +16,21 @@ Solid 支持 JSX、标签模板字面量 和 Solid HyperScript 变体这 3 种 Solid 尝试尽可能地与 HTML 的 attribute 保持一致,包括不区分属性的大小写。 -原生元素 JSX 上的大多数 attribute 都被设置为 DOM attribute。 静态值会直接内置到克隆模板中。 也有例外,诸如 `class`、`style`、`value`、`innerHTML`之类会提供了额外的功能。 +原生元素 JSX 上的大多数 attribute 都被设置为 DOM attribute。静态值会直接内置到克隆模板中。也有例外,诸如 `class`、`style`、`value`、`innerHTML`之类会提供了额外的功能。 -但是,自定义元素(内置的原生元素除外)在动态时默视为认为 property。 这是为了处理更复杂的数据类型。 为了遵循习惯,Solid 直接将蛇形命名(`some-attr`)转化为驼峰命名(`someAttr`)。 +但是,自定义元素(内置的原生元素除外)在动态时默视为认为 property。这是为了处理更复杂的数据类型。为了遵循习惯,Solid 直接将蛇形命名(`some-attr`)转化为驼峰命名(`someAttr`)。 -但是,也可以使用命名空间指令直接控制该行为。 你可以使用 `attr:` 指定 attribute 或者使用 `prop:` 指定 property +但是,也可以使用命名空间指令直接控制该行为。你可以使用 `attr:` 指定 attribute 或者使用 `prop:` 指定 property ```jsx ``` -> **注意:** 静态 attribute 是作为 html 克隆模板的一部分被创建的。 固定和动态表达式随后按 JSX 绑定顺序应用。 虽然这对大多数 DOM 元素来说都无所谓顺序,但是对诸如带有 `type='range'` 的 input 元素来说,顺序很重要。 绑定元素时请牢记这一点。 +> **注意:** 静态 attribute 是作为 html 克隆模板的一部分被创建的。固定和动态表达式随后按 JSX 绑定顺序应用。虽然这对大多数 DOM 元素来说都无所谓顺序,但是对诸如带有 `type='range'` 的 input 元素来说,顺序很重要。绑定元素时请牢记这一点。 ## 入口 -挂载 Solid 应用最简单方法是从 `solid-js/web` 导入 `render`。 `render` 接收一个函数作为第一个参数,接收挂载容器作为第二个参数,并返回一个销毁方法。 这个 `render` 函数会自动创建响应式根节点根并在挂载容器中处理渲染工作。 为了获得最佳性能,建议使用没有子元素的元素。 +挂载 Solid 应用最简单方法是从 `solid-js/web` 导入 `render`。`render` 接收一个函数作为第一个参数,接收挂载容器作为第二个参数,并返回一个销毁方法。这个 `render` 函数会自动创建响应式根节点根并在挂载容器中处理渲染工作。为了获得最佳性能,建议使用没有子元素的元素。 ```jsx import { render } from "solid-js/web"; @@ -38,11 +38,11 @@ import { render } from "solid-js/web"; render(() => , document.getElementById("main")); ``` -> **重要** 第一个参数必须是一个函数。 否则 Solid 无法正确跟踪和调度响应系统。 偷懒将导致你的 Effect 无法运行。 +> **重要** 第一个参数必须是一个函数。否则 Solid 无法正确跟踪和调度响应系统。偷懒将导致你的 Effect 无法运行。 ## 组件 -Solid 组件通常是采用 Pascal(大写)命名风格的函数。 组件第一个参数接收 props 对象,最终返回真实的 DOM 节点。 +Solid 组件通常是采用 Pascal(大写)命名风格的函数。组件第一个参数接收 props 对象,最终返回真实的 DOM 节点。 ```jsx const Parent = () => ( @@ -65,7 +65,7 @@ const Label = props => ( ## Props -与 React、Vue、Angular 以及其他框架非常相似,Solid 允许你在组件上定义 property,将数据传递给子组件。 这里的父组件通过 `greeting` property 将字符串 “Hello” 传递给 `Label` 组件。 +与 React、Vue、Angular 以及其他框架非常相似,Solid 允许你在组件上定义 property,将数据传递给子组件。这里的父组件通过 `greeting` property 将字符串 “Hello” 传递给 `Label` 组件。 ```jsx const Parent = () => ( @@ -77,7 +77,7 @@ const Parent = () => ( ); ``` -在上面的例子中,在 `greeting` 上设置的值是静态的,但我们也可以设置动态值。 例如: +在上面的例子中,在 `greeting` 上设置的值是静态的,但我们也可以设置动态值。例如: ```jsx const Parent = () => { @@ -104,7 +104,7 @@ const Label = props => ( ); ``` -与其他框架不同,你不能在组件的 `props` 上使用对象解构。 这是因为 `props` 对象在底层依赖对象的 getter 来惰性获取值。 使用对象解构破坏了 props 的响应性。 +与其他框架不同,你不能在组件的 `props` 上使用对象解构。这是因为 `props` 对象在底层依赖对象的 getter 来惰性获取值。使用对象解构破坏了 props 的响应性。 这个例子展示了在 Solid 中访问 props 的正确方式: @@ -121,7 +121,7 @@ const MyComponent = props =>
{props.name}
; const MyComponent = ({ name }) =>
{name}
; ``` -虽然 props 对象在使用时看起来像一个普通对象(Typescript 用户会注意到它的类型像普通对象),但实际上它是响应式的 —— 有点类似于 Signal。 这有几个含义。 +虽然 props 对象在使用时看起来像一个普通对象(Typescript 用户会注意到它的类型像普通对象),但实际上它是响应式的 —— 有点类似于 Signal。这有几个含义。 因为与大多数 JSX 框架不同,Solid 的函数组件只执行一次(而不是每个渲染周期都执行),所以下面的示例不会按预期工作。 @@ -146,11 +146,11 @@ export default function Form() { } ``` -在这个例子中,我们期望的是 `BasicComponent` 显示输入到 `input` 中的当前值。 但是,提醒一下,`BasicComponent` 函数只会在组件最初创建时执行一次。 此时(在创建时),`props.value` 将等于 `''`。 这意味着 `BasicComponent` 中的 `const value` 将解析为 `'default'` 并且永远不会更新。 虽然 `props` 对象是响应式的,访问 `const value = props.value || 'default';` 中的 props 就超出了 Solid 的可观察范围,因此当 props 更改时组件不会自动重新求值。 +在这个例子中,我们期望的是 `BasicComponent` 显示输入到 `input` 中的当前值。但是,提醒一下,`BasicComponent` 函数只会在组件最初创建时执行一次。此时(在创建时),`props.value` 将等于 `''`。这意味着 `BasicComponent` 中的 `const value` 将解析为 `'default'` 并且永远不会更新。虽然 `props` 对象是响应式的,访问 `const value = props.value || 'default';` 中的 props 就超出了 Solid 的可观察范围,因此当 props 更改时组件不会自动重新求值。 那么我们该如何解决我们的问题呢? -嗯,一般来说,我们需要在 Solid 可以观察到的地方访问 `props`。 通常,这意味着在 JSX 内或在 `createMemo`、`createEffect` 或 thunk(`() => ...`) 内。 这里有一种按照你的预期工作的解决方案: +嗯,一般来说,我们需要在 Solid 可以观察到的地方访问 `props`。通常,这意味着在 JSX 内或在 `createMemo`、`createEffect` 或 thunk(`() => ...`) 内。这里有一种按照你的预期工作的解决方案: ```jsx const BasicComponent = props => { @@ -168,7 +168,7 @@ const BasicComponent = props => { }; ``` -另一种方案,如果这是一个耗时计算的场景,那应该使用 `createMemo`。 例如: +另一种方案,如果这是一个耗时计算的场景,那应该使用 `createMemo`。例如: ```jsx const BasicComponent = props => { @@ -206,7 +206,7 @@ const BasicComponent = props => { }; ``` -Solid 的组件是其性能的核心部分。 Solid 所谓的 “消失” 组件是通过 prop 惰性求值实现的。 而不是对 prop 表达式进行即时求值并传递,它推迟到了 child 中访问 prop 再执行。这样的话我们将执行推迟到最后一刻 —— 通常在 DOM 绑定,从而最大限度地提高性能。这么做不仅使层次结构扁平化而且消除了维护组件树的需要。 +Solid 的组件是其性能的核心部分。Solid 所谓的 “消失” 组件是通过 prop 惰性求值实现的。而不是对 prop 表达式进行即时求值并传递,它推迟到了 child 中访问 prop 再执行。这样的话我们将执行推迟到最后一刻 —— 通常在 DOM 绑定,从而最大限度地提高性能。这么做不仅使层次结构扁平化而且消除了维护组件树的需要。 ```jsx ; @@ -243,7 +243,7 @@ const [local, others] = splitProps(props, ["className"]) ## Children -Solid 处理 JSX Children 的方式类似 React。 单个 child 是 `props.children` 上的单个值,多个 child 是通过值成员数组处理的。 通常,你将 child 传递给 JSX 视图。 但是,如果您想与它们交互,建议使用 `children` 工具函数,它能够解析任何下游流程控制并返回 Memo。 +Solid 处理 JSX Children 的方式类似 React。单个 child 是 `props.children` 上的单个值,多个 child 是通过值成员数组处理的。通常,你将 child 传递给 JSX 视图。但是,如果你想与它们交互,建议使用 `children` 工具函数,它能够解析任何下游流程控制并返回 Memo。 ```jsx // 单个子节点 @@ -278,4 +278,4 @@ const List = (props) => { ; ``` -**重要:** Solid 将 child 标签视为耗性能的表达式,并用与动态响应式表达式相同的方式包装它们。 这意味着他们利用访问 `prop` 进行了惰性求值。 在视图中使用它们之前,请小心避免多次访问它们或者进行解构。 这是因为 Solid 没有大费周章地提前创建虚拟 DOM 节点然后对它们进行 diff 操作,所以这些 `props` 的解析必须是惰性且经过斟酌的。 如果你希望这样做,请使用 `children` 工具函数,因为 `children` 会缓存这些值。 +**重要:** Solid 将 child 标签视为耗性能的表达式,并用与动态响应式表达式相同的方式包装它们。这意味着他们利用访问 `prop` 进行了惰性求值。在视图中使用它们之前,请小心避免多次访问它们或者进行解构。这是因为 Solid 没有大费周章地提前创建虚拟 DOM 节点然后对它们进行 diff 操作,所以这些 `props` 的解析必须是惰性且经过斟酌的。如果你希望这样做,请使用 `children` 工具函数,因为 `children` 会缓存这些值。 diff --git a/documentation/zh-cn/guides/server.md b/documentation/zh-cn/guides/server.md index 86b9daf57..e88842aba 100644 --- a/documentation/zh-cn/guides/server.md +++ b/documentation/zh-cn/guides/server.md @@ -1,8 +1,8 @@ # SSR -Solid 通过将 JSX 模板编译为无比高效的字符串附加代码来处理服务器渲染。这可以通过传入 `generate: "ssr"` 到 babel 插件或者预设来实现。 对于客户端和服务端而言,你都需要传入 `hydratable: true` 来生成注水兼容代码。 +Solid 通过将 JSX 模板编译为无比高效的字符串附加代码来处理服务器渲染。这可以通过传入 `generate: "ssr"` 到 babel 插件或者预设来实现。对于客户端和服务端而言,你都需要传入 `hydratable: true` 来生成注水兼容代码。 -在 node 环境中运行时,`solid-js` 和 `solid-js/web` 运行时被置换为非响应式的对应。 对于其他环境,你需要将导出条件设置为 `node` 来打包服务端代码。 大多数构建工具都有办法做到这一点。 一般来说,我们还是建议使用 `solid` 的导出条件,并建议库在`solid` 的导出条件下输出源代码。 +在 node 环境中运行时,`solid-js` 和 `solid-js/web` 运行时被置换为非响应式的对应。对于其他环境,你需要将导出条件设置为 `node` 来打包服务端代码。大多数构建工具都有办法做到这一点。一般来说,我们还是建议使用 `solid` 的导出条件,并建议库在`solid` 的导出条件下输出源代码。 构建 SSR 肯定需要更多配置,因为我们需要生成 2 个单独的包。客户端入口应该使用 `hydrate`: @@ -12,9 +12,9 @@ import { hydrate } from "solid-js/web"; hydrate(() => , document); ``` -_注意:可以从文档根节点进行渲染和注水。 这允许我们在 JSX 中描述完整的视图。_ +_注意:可以从文档根节点进行渲染和注水。这允许我们在 JSX 中描述完整的视图。_ -服务器入口可以使用 Solid 提供的四个渲染函数之一。 每个都会输出对应产物或者是一个要插入到文档头部的脚本标签。 +服务器入口可以使用 Solid 提供的四个渲染函数之一。每个都会输出对应产物或者是一个要插入到文档头部的脚本标签。 ```jsx import { @@ -38,7 +38,7 @@ const { readable, writable } = new TransformStream(); pipeToWritable(() => , writable); ``` -为方便起见,`solid-js/web` 导出了一个十分有用的 `isServer` 标志。 这样大多数打包工具将能够在此标志下对任意代码进行的 treeshake 操作,或者仅在此标志下使用浏览器端之外的代码。 +为方便起见,`solid-js/web` 导出了一个十分有用的 `isServer` 标志。这样大多数打包工具将能够在此标志下对任意代码进行的 treeshake 操作,或者仅在此标志下使用浏览器端之外的代码。 ```jsx import { isServer } from "solid-js/web"; @@ -52,7 +52,7 @@ if (isServer) { ## 注水脚本 -甚至为了在 Solid 运行时加载之前渐进式注水,需要在页面上插入一个特殊的脚本。 这个脚本可以通过 `generateHydrationScript` 生成和插入,也可以使用 `` JSX 标签。 +甚至为了在 Solid 运行时加载之前渐进式注水,需要在页面上插入一个特殊的脚本。这个脚本可以通过 `generateHydrationScript` 生成和插入,也可以使用 `` JSX 标签。 ```js import { generateHydrationScript } from "solid-js/web"; @@ -92,7 +92,7 @@ const App = () => { }; ``` -当从文档中插入客户端不可用的资源来进行注水时,就会把事情搞砸。 Solid 提供了一个 `` 组件,其子组件可以在服务器上正常工作,但不会在浏览器中注水。 +当从文档中插入客户端不可用的资源来进行注水时,就会把事情搞砸。Solid 提供了一个 `` 组件,其子组件可以在服务器上正常工作,但不会在浏览器中注水。 ```jsx @@ -104,7 +104,7 @@ const App = () => { ## 异步和流式 SSR -异步和流式服务端渲染机制建立在 Solid 对应用如何工作的了解之上。它通过在服务器上使用 Suspense 和 Resource API 来实现,而不是提前获取然后渲染。Solid 获取资源数据在服务器上行为,就像在客户端上一样。 代码的编写方式和执行模式完全相同。 +异步和流式服务端渲染机制建立在 Solid 对应用如何工作的了解之上。它通过在服务器上使用 Suspense 和 Resource API 来实现,而不是提前获取然后渲染。Solid 获取资源数据在服务器上行为,就像在客户端上一样。代码的编写方式和执行模式完全相同。 异步渲染会等到所有 Suspense 边界解析后发送结果(或在静态站点生成的情况下将它们写入文件)。 @@ -118,11 +118,11 @@ const App = () => { ## SSR 注意事项 -Solid 的 SSR 同构解决方案非常强大,因为你可以将代码编写一份代码就差不多可以在在两种环境中运行。然而,有人期望这会增加注水功能。 大多数情况下,客户端中渲染的视图与服务器上渲染的视图大体相同。精确到文本可能不同,但在结构上标记应该是相同的。 +Solid 的 SSR 同构解决方案非常强大,因为你可以将代码编写一份代码就差不多可以在在两种环境中运行。然而,有人期望这会增加注水功能。大多数情况下,客户端中渲染的视图与服务器上渲染的视图大体相同。精确到文本可能不同,但在结构上标记应该是相同的。 -我们使用在服务端中渲染的标记来匹配客户端的元素和资源位置。为此,客户端和服务器应该具有相同的组件。鉴于 Solid 在客户端和服务器上以相同的方式渲染,这根本不是问题。但是目前没有办法在服务器上渲染不会在客户端注水的东西。 也没有办法对整个页面进行部分注水,也无法为其生成注水标记。 要么全有要么全无。部分注水是我们未来想要探索的东西。 +我们使用在服务端中渲染的标记来匹配客户端的元素和资源位置。为此,客户端和服务器应该具有相同的组件。鉴于 Solid 在客户端和服务器上以相同的方式渲染,这根本不是问题。但是目前没有办法在服务器上渲染不会在客户端注水的东西。也没有办法对整个页面进行部分注水,也无法为其生成注水标记。要么全有要么全无。部分注水是我们未来想要探索的东西。 -最后,所有资源都需要在 `render` 树下定义。它们会自动序列化并在浏览器中提取,这样起作用是因为 `render` 或 `pipeTo` 方法会跟踪渲染的进度。 如果它们是在独立的上下文中创建的,我们就无法做到跟踪。同理可得,服务器上没有响应性,因此不要在初始渲染时更新 signal,并期望它们传递到树的上层。虽然我们有 Suspense 边界,但 Solid 的 SSR 基本是自上而下的。 +最后,所有资源都需要在 `render` 树下定义。它们会自动序列化并在浏览器中提取,这样起作用是因为 `render` 或 `pipeTo` 方法会跟踪渲染的进度。如果它们是在独立的上下文中创建的,我们就无法做到跟踪。同理可得,服务器上没有响应性,因此不要在初始渲染时更新 signal,并期望它们传递到树的上层。虽然我们有 Suspense 边界,但 Solid 的 SSR 基本是自上而下的。 ## SSR 入门 diff --git a/documentation/zh-cn/resources/articles.md b/documentation/zh-cn/resources/articles.md index dbc236da9..0f36795b8 100644 --- a/documentation/zh-cn/resources/articles.md +++ b/documentation/zh-cn/resources/articles.md @@ -23,7 +23,7 @@ - [Why I am not a fan of Single File Components](https://dev.to/ryansolid/why-i-m-not-a-fan-of-single-file-components-3bfl) 探索 Solid 模板的优势 - [How we wrote the Fastest JavaScript Framework, Again!](https://levelup.gitconnected.com/how-we-wrote-the-fastest-javascript-ui-framework-again-db097ddd99b6) 这次我们征服了服务器 - [Solid - The best JavaScript UI library?](https://areknawo.com/solid-the-best-javascript-ui-library/) -- [SolidJS: Reactivity to Rendering](https://indepth.dev/solidjs-reactivity-to-rendering/) 从头开始构建 Solid 的响应式式渲染器 +- [SolidJS: Reactivity to Rendering](https://indepth.dev/solidjs-reactivity-to-rendering/) 从头开始构建 Solid 的响应式渲染器 - [Comparing reactivity models - React vs Vue vs Svelte vs MobX vs Solid vs Redux](https://dev.to/lloyds-digital/comparing-reactivity-models-react-vs-vue-vs-svelte-vs-mobx-vs-solid-29m8) - [Best React-like JSX UI Libraries in 2020](https://areknawo.com/best-react-like-jsx-ui-libraries-in-2020/) - [Exploring Reactivity Patterns in 2020](https://indepth.dev/exploring-the-state-of-reactivity-patterns-in-2020/) 前端的最新趋势是什么? diff --git a/documentation/zh-cn/resources/projects.md b/documentation/zh-cn/resources/projects.md index 0514e4702..132dce9b8 100644 --- a/documentation/zh-cn/resources/projects.md +++ b/documentation/zh-cn/resources/projects.md @@ -67,4 +67,4 @@ 用于 DOM 表达式的 HyperScript API。 - [Surplus](https://github.com/adamhaile/surplus) 原始的响应式 JSX 库 -知道任何其他优秀的 Solid 项目和库吗? 请提交它们。 我们很高兴看到你在做什么。 +知道任何其他优秀的 Solid 项目和库吗?请提交它们。我们很高兴看到你在做什么。