如何像 Vue 一样从父层向 Blazor 组件随机添加 CSS 属性?

Posted

技术标签:

【中文标题】如何像 Vue 一样从父层向 Blazor 组件随机添加 CSS 属性?【英文标题】:How can I randomly add CSS attributes to Blazor component from parent layer as Vue did? 【发布时间】:2019-11-15 20:48:19 【问题描述】:

由于我想设计一些可重用的 Blazor 组件,我希望它们可以具有这样的功能:

假设我有一个自定义组件“MyComponent”,我可以在使用它时添加任何 CSS 属性:

<MyComponent Class="custom-css1 custom-css2">
    some child content...
</MyComponent>

在 MyComponent 中,我通常会像这样将一些常见的 CSS 属性固定到顶部 wapper:

<div class="fixed-css1 fixed-css2">
    some child content...
</div>

这意味着我必须将 CSS 属性的两个部分组合在一起以制作最终的 html,如下所示:

<div class="fixed-css1 fixed-css2 custom-css1 custom-css2">
    some child content...
</div>

所以我想我应该有这个模式:

<div class="@Classes">
    some child content...
</div>

@functions


    [Parameter]
    private string Class  get; set;  = "";

    private string fixedClass = "fixed-css1 fixed-css2";

    private string Classes
    
        get
        
            return $"fixedClass Class";
        
    

为了减少冗余代码,我可以创建一个基类,它具有受保护的 Class 属性以及它固有的每个组件,但我仍然无法避免在每个组件中编写相同的组合代码。我希望有一些解决方案可以直接在我的基类中添加这些自定义 CSS,我想我可以通过覆盖 ComponentBase clss 中的 BuildRenderTree 方法来实现这一点:

protected override void BuildRenderTree(RenderTreeBuilder builder)
        
            base.BuildRenderTree(builder);
        

但不幸的是,我尝试了所有手动构建的方法,但不知道如何完成。我不知道如何获取我的 HTML 元素(例如“div”)并向其添加额外的 CSS 属性。

所有这些都是关于做一个 Vue 可以轻松做到的功能。在 Vue 代码中,我们当然可以为组件添加任何属性并将它们传递给组件中的第一个元素。

谁能帮我完成这个目标或给我一些建议?

【问题讨论】:

我能问一下为什么使用您在基类上识别的模式不能解决您的问题吗?您只需使用 @Classes 即可应用组合的 CSS。这实际上正是 Blazor 团队用来在表单输入控件上允许自定义 CSS 类的方法。 对不起,我可能没有清楚地描述我的观点,我希望将此模式应用于我的所有组件,这意味着我必须一次又一次地重复相同的组合代码(除了 Class属性),它很丑。 【参考方案1】:

我认为您的方法很好,它只需要围绕它进行一些抽象,以使其在多个组件之间具有可读性和易于管理。

这就是我创建这个简单的辅助函数库的原因。这正是您在代码中所做的,但提供了一个 API 以保持一致性。

https://www.nuget.org/packages/BlazorComponentUtilities/

【讨论】:

谢谢,我会深入研究一下这个建议。 太棒了!这正是我想要的,还有更多,感谢您的贡献。 帮助器设计得非常好,甚至可以处理“属性飞溅”。 +1【参考方案2】:

据我所知,目前 Blazor 不提供处理 CSS 的内置方式,并且 Blazor 最佳实践和模式尚不可用,因此您可以以任何您认为合适的方式处理 CSS,包括 JSI​​nterop .

以下是我认为对您非常有用的库的链接: https://github.com/chanan/BlazorStyled

希望这会有所帮助...

【讨论】:

谢谢,这个包给了我另一种思路,很有帮助。【参考方案3】:

试试这个,我用过,效果很好,很简单

<div class="fixed-css1 fixed-css2 @(Class)">
    some child content...
</div>

我不确定这是否是一种不好的做法,

它会阻止 itellisense 在类属性中正常工作, 但这很容易实现,只需将其添加到属性的末尾如果您需要使用智能感知进行更改,请在 @(class) 之前添加“”,进行更改,然后删除“”

如果组件上没有设置 Class 参数,它可能会在类字符串中留下一个空格 例如&lt;div class="fixed-css1 fixed-css2 "&gt;(末尾有空格)

【讨论】:

谢谢,我已经按照您提供的类似方式解决了这个问题。美好的一天。【参考方案4】:

您可以通过两种方式做到这一点。

第一种方式,您可以使用字典从父级传递给子级,如下所示。我在这个例子中添加了required 属性。

子组件:

<input id="firstName" @attributes="InputAttributes" />

@code 
    [Parameter]
    public Dictionary<string, object> InputAttributes  get; set;  = 
        new Dictionary<string, object>() 
        
             "placeholder", "Child Component Placeholder" 
        ;

父组件:

<ChildComponent InputAttributes="attributesFromParent">
</ChildComponent>

@code 
    public Dictionary<string, object> attributesFromParent  get; set;  = 
        new Dictionary<string, object>() 
        
             "required", "required" ,
             "placeholder", "Parent Component Placeholder" 
        ;

第二种方式,你可以将CaptureUnmatchedValues设置为true。并直接将maxlength之类的属性从父级传递给子级。

子组件:

<input id="firstName" @attributes="InputAttributes" />

@code 
    [Parameter(CaptureUnmatchedValues = true)]
    public Dictionary<string, object> InputAttributes  get; set;  = 
        new Dictionary<string, object>() 
        
             "placeholder", "Child Component Placeholder" 
        ;

父组件:

<ChildComponent InputAttributes="attributesFromParent" maxlength="15">
</ChildComponent>

@code 
    public Dictionary<string, object> attributesFromParent  get; set;  = 
        new Dictionary<string, object>() 
        
             "required", "required" ,
             "placeholder", "Parent Component Placeholder" 
        ;

参考: https://youtu.be/gClG243kn1o 和 https://www.pragimtech.com/blog/blazor/blazor-arbitrary-attributes/

【讨论】:

以上是关于如何像 Vue 一样从父层向 Blazor 组件随机添加 CSS 属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何从父级修改组件的样式?

使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件

从父组件vue访问第三方子组件

Blazor University 组件 — 级联值

如何让 MudBlazor 组件像普通 HTML 元素一样工作

使用 vue 和 vue router 将数据传递给组件并从父级访问数据