author-component
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAuthor Blazor Component
编写Blazor组件
Core Rules
核心规则
- Data flows down via . Events flow up via
[Parameter](neverEventCallback<T>/Action).Func - Never mutate properties. Copy to a private field in
[Parameter].OnParametersSet - Use — never
[Parameter] public T Prop { get; set; }orrequired(causes BL0007).init - Use for required parameters.
[EditorRequired] - Handle all states: loading, empty, loaded, error — each with /
@if.@else - Use on repeated elements in loops for efficient diffing.
@key - Use (not
IReadOnlyList<T>) for collection parameters.IEnumerable<T>
- 数据通过向下传递,事件通过
[Parameter]向上传递(绝不要使用EventCallback<T>/Action)。Func - 绝不要修改属性。在
[Parameter]中复制到私有字段。OnParametersSet - 使用——绝不要使用
[Parameter] public T Prop { get; set; }或required(会导致BL0007错误)。init - 对必填参数使用。
[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 templateUse for generic components.
@typeparam TItemcsharp
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; } // 泛型模板泛型组件使用。
@typeparam TItemFile Patterns
文件模式
- Single-file: with
.razorblock when logic < ~50 lines.@code - Code-behind: +
.razorwith.razor.cswhen logic > ~50 lines.partial class
- 单文件:当逻辑代码少于约50行时,使用包含块的
@code文件。.razor - 代码后置:当逻辑代码多于约50行时,使用+
.razor搭配.razor.cs。partial class
Disposal
资源清理
Implement (not ) when the component owns subscriptions, timers, or CTS.
In : unsubscribe (), cancel CTS, dispose resources. Never call .
IAsyncDisposableIDisposableDisposeAsync-=StateHasChanged当组件拥有订阅、计时器或CTS时,实现(而非)。
在中:取消订阅()、取消CTS、释放资源。绝不要调用。
IAsyncDisposableIDisposableDisposeAsync-=StateHasChangedAsync Patterns
异步模式
- every async operation. Never use
await,.Result,.Wait(),Task.Run,ContinueWith.Thread.Start - Debounce: +
Task.Delay. Cancel old CTS, create new, await delay, do work. Never useCancellationTokenSourceorSystem.Threading.Timer.System.Timers.Timer - Polling: Loop in with
OnInitializedAsync— stays on sync context.await Task.Delay(interval, token) - External events (): Use
Action<T>handler +async void+await InvokeAsync(() => { state++; StateHasChanged(); })→catch. NeverDispatchExceptionAsync._ = InvokeAsync(...) - Cancel CTS in . Don't catch
DisposeAsync— use CTS cancellation.ObjectDisposedException
- 对所有异步操作使用。绝不要使用
await、.Result、.Wait()、Task.Run、ContinueWith。Thread.Start - 防抖:使用+
Task.Delay。取消旧的CTS,创建新的,等待延迟后执行操作。绝不要使用CancellationTokenSource或System.Threading.Timer。System.Timers.Timer - 轮询:在中循环,使用
OnInitializedAsync——保持在同步上下文。await Task.Delay(interval, token) - 外部事件():使用
Action<T>处理器 +async void+await InvokeAsync(() => { state++; StateHasChanged(); })→catch。绝不要使用DispatchExceptionAsync。_ = InvokeAsync(...) - 在中取消CTS。不要捕获
DisposeAsync——使用CTS取消。ObjectDisposedException
Don'ts
注意事项
- /
requiredoninit— runtime failure[Parameter] - Mutate — copy to private field in
[Parameter]OnParametersSet - /
Actionfor events — useFuncEventCallback<T> - /
Task.Run/.Result/Timer for debounce — deadlock or thread-pool escape.Wait() - Inline attributes — use CSS classes or
styleattributesdata-* - — use
catch { throw; }guard or let exceptions propagatewhen - Gold-plating: ARIA, wrapper divs, accessibility features not requested
- — swallows exceptions; use
_ = InvokeAsync(...)+async voidDispatchExceptionAsync
- 在上使用
[Parameter]/required——会导致运行时失败init - 修改——应在
[Parameter]中复制到私有字段OnParametersSet - 使用/
Action处理事件——请使用FuncEventCallback<T> - 使用/
Task.Run/.Result/Timer实现防抖——会导致死锁或线程池逃逸.Wait() - 内联属性——请使用CSS类或
style属性data-* - ——使用
catch { throw; }守卫或让异常传播when - 过度设计:未要求的ARIA、包装div、无障碍功能
- ——会吞掉异常;请使用
_ = InvokeAsync(...)+async voidDispatchExceptionAsync