Skip to content

组件

组件是创建 JSX 标记的构建块。每个组件都是一个实现 PC 类型(用于同步组件)或 APC 类型(用于异步组件)的函数。此类函数的第一个参数是参数,第二个参数是可用的 PreffX 工具。

实现特性:

  1. 响应式:使用信号系统 (@preact/signals-core) 创建和跟踪响应值。只有这些值才会触发重新渲染。
  2. 生命周期管理:在组件挂载和卸载时运行回调,并自动移除效果
  3. 将 PreffX 工具作为第二个参数传递:所需的一切都在参数中,只需要从 PreffX 本身导入类型
  4. 支持异步函数:同时支持同步和异步函数,在承诺解析时自动重新渲染 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 根之外渲染元素

根据 Apache-2.0 许可证发布。