我有以下一段代码:
@page "somePage"
<TeamsApplication RequireAuthentication="true">
<ApplicationTemplate Context="context">
Some HTML...
@*context works here*@
</ApplicationTemplate>
</TeamsApplication>
@code{
//context doesnt work here
}
在ApplicationTemplate标签内,我可以访问上下文对象实例,但不能在代码部分这样做。有没有办法访问那个实例和它的值?
一个熟悉的问题,从一组想要共享数据和状态的组件构建页面。你可以把它们连在一起,但你很快就会变成意大利面。
解决方案是将数据和状态与UI分离。UI代码驻留在组件中,而数据和状态驻留在一个服务中——通常称为ViewService。服务通常是限定范围的,即每个SPA会话一个。每个组件注入服务,然后访问共享的数据/状态。你在服务中使用事件来通知组件它们需要响应的更改——通常是重新呈现。
在您的问题中,服务将持有context
。然后TeamsApplication
、ApplicationTemplate
、SomePage
和其他组件都将注入服务并访问context
。
如果你想要一个有效的例子,问,我会加一个到这个答案。
属性通常是向下的,而不是向上的。所以Context
属性不会像那样工作。我能想到的最简单的解决方案是一个EventCallback,这样ApplicationTemplate
就会向父进程发送一个消息,告诉它Context是可用的
ApplicationTemplate.razor
[Parameter] public EventCallback<Context> ContextChanged { get; set; }
/// <summary>
/// Context was set from somewhere
/// </summary>
async Task ContextSet(Context newValue)
{
// notify anyone listening to ContextChanged
await ContextChanged.InvokeAsync(newValue);
}
然后在你的页面逻辑中,你听这个事件回调:
<TeamsApplication>
<ApplicationTemplate ContextChanged=HandleContextChanged>
@* todo *@
</ApplicationTemplate>
</TeamsApplication>
@code
{
/// <summary>
/// Handle event from ApplicationTemplate
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
async Task HandleContextChanged(Context context)
{
// context is now available
}
}
您可以创建一个接受与上下文类型相同类型的参数的函数,因此您可以访问该函数,但问题是:您需要该上下文做什么?
如果你需要创建一个需要访问上下文的自定义组件,把它传递给另一个子组件,然后创建一个类型为RenderFragment的[Parameter],这样你就可以随心所欲地处理它了。
你甚至可以创建一个局部函数来渲染RenderFragment,但是Razor的语法对于这类东西来说是相当笨拙的,并且有一些bug
例如,我有一个这样的方法
public RenderFragment DefaultActionTemplate(PanelAction action) =>@:@{
if (action.IsToggle) {
<div>Toggle</div>
}
else {
<div>Button</div>
}
}
;
你可以做同样的事情,使用你的上下文类型而不是我的PanelAction,概念是一样的
正如我告诉过你的那样,语法很笨拙,你在末尾看到的分号需要在新行上,不能在右花括号旁边参见此问题:https://github.com/dotnet/aspnetcore/issues/11612