author-component

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Author Blazor Component

编写Blazor组件

Core Rules

核心规则

  • Data flows down via
    [Parameter]
    . Events flow up via
    EventCallback<T>
    (never
    Action
    /
    Func
    ).
  • Never mutate
    [Parameter]
    properties. Copy to a private field in
    OnParametersSet
    .
  • Use
    [Parameter] public T Prop { get; set; }
    — never
    required
    or
    init
    (causes BL0007).
  • Use
    [EditorRequired]
    for required parameters.
  • Handle all states: loading, empty, loaded, error — each with
    @if
    /
    @else
    .
  • Use
    @key
    on repeated elements in loops for efficient diffing.
  • Use
    IReadOnlyList<T>
    (not
    IEnumerable<T>
    ) for collection parameters.
  • 数据通过
    [Parameter]
    向下传递,事件通过
    EventCallback<T>
    向上传递(绝不要使用
    Action
    /
    Func
    )。
  • 绝不要修改
    [Parameter]
    属性。在
    OnParametersSet
    中复制到私有字段。
  • 使用
    [Parameter] public T Prop { get; set; }
    ——绝不要使用
    required
    init
    (会导致BL0007错误)。
  • 对必填参数使用
    [EditorRequired]
  • 处理所有状态:加载中、空状态、已加载、错误——分别使用
    @if
    /
    @else
    实现。
  • 在循环的重复元素上使用
    @key
    以实现高效差异对比。
  • 集合参数使用
    IReadOnlyList<T>
    (而非
    IEnumerable<T>
    )。

RenderFragment & Generics

RenderFragment与泛型

csharp
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; }  // generic template
Use
@typeparam TItem
for generic components.
csharp
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; }  // 泛型模板
泛型组件使用
@typeparam TItem

File Patterns

文件模式

  • Single-file:
    .razor
    with
    @code
    block when logic < ~50 lines.
  • Code-behind:
    .razor
    +
    .razor.cs
    with
    partial class
    when logic > ~50 lines.
  • 单文件:当逻辑代码少于约50行时,使用包含
    @code
    块的
    .razor
    文件。
  • 代码后置:当逻辑代码多于约50行时,使用
    .razor
    +
    .razor.cs
    搭配
    partial class

Disposal

资源清理

Implement
IAsyncDisposable
(not
IDisposable
) when the component owns subscriptions, timers, or CTS. In
DisposeAsync
: unsubscribe (
-=
), cancel CTS, dispose resources. Never call
StateHasChanged
.
当组件拥有订阅、计时器或CTS时,实现
IAsyncDisposable
(而非
IDisposable
)。 在
DisposeAsync
中:取消订阅(
-=
)、取消CTS、释放资源。绝不要调用
StateHasChanged

Async Patterns

异步模式

  • await
    every async operation. Never use
    .Result
    ,
    .Wait()
    ,
    Task.Run
    ,
    ContinueWith
    ,
    Thread.Start
    .
  • Debounce:
    Task.Delay
    +
    CancellationTokenSource
    . Cancel old CTS, create new, await delay, do work. Never use
    System.Threading.Timer
    or
    System.Timers.Timer
    .
  • Polling: Loop in
    OnInitializedAsync
    with
    await Task.Delay(interval, token)
    — stays on sync context.
  • External events (
    Action<T>
    ): Use
    async void
    handler +
    await InvokeAsync(() => { state++; StateHasChanged(); })
    +
    catch
    DispatchExceptionAsync
    . Never
    _ = InvokeAsync(...)
    .
  • Cancel CTS in
    DisposeAsync
    . Don't catch
    ObjectDisposedException
    — use CTS cancellation.
  • 对所有异步操作使用
    await
    。绝不要使用
    .Result
    .Wait()
    Task.Run
    ContinueWith
    Thread.Start
  • 防抖:使用
    Task.Delay
    +
    CancellationTokenSource
    。取消旧的CTS,创建新的,等待延迟后执行操作。绝不要使用
    System.Threading.Timer
    System.Timers.Timer
  • 轮询:在
    OnInitializedAsync
    中循环,使用
    await Task.Delay(interval, token)
    ——保持在同步上下文。
  • 外部事件
    Action<T>
    ):使用
    async void
    处理器 +
    await InvokeAsync(() => { state++; StateHasChanged(); })
    +
    catch
    DispatchExceptionAsync
    。绝不要使用
    _ = InvokeAsync(...)
  • DisposeAsync
    中取消CTS。不要捕获
    ObjectDisposedException
    ——使用CTS取消。

Don'ts

注意事项

  • required
    /
    init
    on
    [Parameter]
    — runtime failure
  • Mutate
    [Parameter]
    — copy to private field in
    OnParametersSet
  • Action
    /
    Func
    for events — use
    EventCallback<T>
  • Task.Run
    /
    .Result
    /
    .Wait()
    /Timer for debounce — deadlock or thread-pool escape
  • Inline
    style
    attributes — use CSS classes or
    data-*
    attributes
  • catch { throw; }
    — use
    when
    guard or let exceptions propagate
  • Gold-plating: ARIA, wrapper divs, accessibility features not requested
  • _ = InvokeAsync(...)
    — swallows exceptions; use
    async void
    +
    DispatchExceptionAsync
  • [Parameter]
    上使用
    required
    /
    init
    ——会导致运行时失败
  • 修改
    [Parameter]
    ——应在
    OnParametersSet
    中复制到私有字段
  • 使用
    Action
    /
    Func
    处理事件——请使用
    EventCallback<T>
  • 使用
    Task.Run
    /
    .Result
    /
    .Wait()
    /Timer实现防抖——会导致死锁或线程池逃逸
  • 内联
    style
    属性——请使用CSS类或
    data-*
    属性
  • catch { throw; }
    ——使用
    when
    守卫或让异常传播
  • 过度设计:未要求的ARIA、包装div、无障碍功能
  • _ = InvokeAsync(...)
    ——会吞掉异常;请使用
    async void
    +
    DispatchExceptionAsync