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

问题描述 投票:0回答:6

由于我想设计一些可重用的 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 代码中,我们当然可以向组件添加任何属性,并将它们传递给组件中的第一个元素。

有人可以帮助我完成这个目标或给我一些建议吗?

c# css asp.net-core razor blazor
6个回答
9
投票

我认为你的方法很好,它只需要一些抽象,以使其可读并易于跨多个组件管理。

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

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


3
投票

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

下面是一个库的链接,我相信对您非常有用: https://github.com/chanan/BlazorStyled

希望这有帮助...


3
投票

试试这个,我用过它,它有效而且简单

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

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

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

如果组件上未设置 Class 参数,则可能会在类字符串中留下空格
例如

<div class="fixed-css1 fixed-css2 ">
(末尾有空格)


2
投票

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

第一种方法,您可以使用字典从父级传递给子级,如下所示。我在此示例中添加了

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/gClG243kn1ohttps://www.pragimtech.com/blog/blazor/blazor-centric-attributes/


2
投票

假设:

  • 您想在父级中添加类
  • 您想在孩子中添加课程
  • 您希望所有类都合并到最终标记中
  • 你想使用
    class
    ...而不是
    Class
    Classes
    Css
    CssClass
    或其他!

ChildComponent.razor

<div @attributes=_additionalAttributes></div>

@code {

  [Parameter(CaptureUnmatchedValues = true)]
  public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; }
    = new Dictionary<string, object>();

  private IReadOnlyDictionary<string, object>? _additionalAttributes;

  protected override void OnParametersSet()
  {
    base.OnParametersSet();

    var parentClasses = AdditionalAttributes.GetValueOrDefault("class", "");
    var classes       = $"foo {parentClasses}".Trim();

    _additionalAttributes = 
      AdditionalAttributes.Where(x => x.Key != "class")
      .Append(KeyValuePair.Create("class", (object)classes))
      .ToDictionary(x => x.Key, x => x.Value);
  }

}

ParentComponent.razor
现在干净了,具有正常名称
class

<ChildComponent class="bar baz" />

@code {
}

哪个渲染:

<div class="foo bar baz"></div>

0
投票

你的模式很好,但可以简化一点。

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

@code
{
    [Parameter]
    private string Class { get; set; } = "";
}

@Class
将打印变量的内容,即附加到组件的类,并且它可以在现有字符串的末尾执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.