组件
组件是创建 JSX 标记的构建块。每个组件都是一个实现 PC 类型(用于同步组件)或 APC 类型(用于异步组件)的函数。此类函数的第一个参数是参数,第二个参数是可用的 PreffX 工具。
实现特性:
- 响应式:使用信号系统 (
@preact/signals-core) 创建和跟踪响应值。只有这些值才会触发重新渲染。 - 生命周期管理:在组件挂载和卸载时运行回调,并自动移除效果
- 将 PreffX 工具作为第二个参数传递:所需的一切都在参数中,只需要从 PreffX 本身导入类型
- 支持异步函数:同时支持同步和异步函数,在承诺解析时自动重新渲染 DOM 树
基本实现
带计数器的最简单组件实现如下:
typescript
import type { PC } from 'preffx';
const MyComponent: PC = (props, { signal, computed }) => {
const { initialCount = 0 } = props;
const count = signal(initialCount);
return (
<div>
<p>Counter: {count}</p>
<button onClick={() => count.value++}>Increase</button>
</div>
);
};
const App: PC = () => {
return <MyComponent
initialCount={5}
/>;
};响应式
为了确保响应式,使用了基于 @preact/signals-core 实现的函数,例如:
signal- 创建用于状态的响应信号,computed- 计算依赖值,effect- 管理副作用。
这些和其他函数完全实现了 Preact Signals 文档 中描述的行为。
组件上下文
对于每个组件实例,都会创建一个扩展父上下文的上下文。这是一个可以从工具中获取的普通对象:
tsx
import type { PC } from 'preffx';
const contextKey = 'ctx-counter';
const AnotherComponent: PC = (props, { context }) => {
// 读取上下文
const counter = context[contextKey];
return <span>
{counter}
</span>;
};
export const App: PC = (props, { signal, context }) => {
const counter = signal(0);
// 修改上下文
context[contextKey] = counter;
return <p>
{valueFromContext}
<AnotherComponent />
</p>;
};生命周期
每个组件都可以使用生命周期工具:
onMount- 在组件挂载时调用 - 在其元素被添加到 DOM 树之后;onDestroy- 在组件销毁时调用 - 在其元素从 DOM 树中移除之前
tsx
import type { PC } from 'preffx';
export const App: PC = (props, { onMount, onDestroy }) => {
const { count } = props;
onMount(() => {
// 一些挂载逻辑
});
onDestroy(() => {
// 一些销毁逻辑
});
return <button
onClick={() => {
count.value += 1
}}
>
Count is {count}
</button>
};ID 生成
id 工具允许为组件内部生成唯一标识符:
tsx
import type { PC } from 'preffx';
export const App: PC = (props, { id }) => {
// 获取唯一 id
const inputId = id();
return <div>
<label>
Password:
<input
type="password"
aria-describedby={inputId}
/>
</label>
<p id={inputId}>
The password should contain at least 18 characters
</p>
</div>;
};特殊组件
在工具中,可以突出显示一些特殊的内置组件:
Catch- 用于组件中的错误处理,For- 用于渲染具有响应式支持的列表,Defer- 用于延迟渲染异步计算的值,Portal- 用于在 PreffX 根之外渲染元素