由于我想设计一些可重用的 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 代码中,我们当然可以向组件添加任何属性,并将它们传递给组件中的第一个元素。
有人可以帮助我完成这个目标或给我一些建议吗?
我认为你的方法很好,它只需要一些抽象,以使其可读并易于跨多个组件管理。
这就是我创建这个简单的辅助函数库的原因。这正是您在代码中所做的,但提供了 API 以保持一致性。
据我所知,目前 Blazor 并未提供处理 CSS 的内置方式,并且 Blazor 最佳实践和模式尚不可用,因此您可以以任何您认为合适的方式处理 CSS,包括 JSInterop。
下面是一个库的链接,我相信对您非常有用: https://github.com/chanan/BlazorStyled
希望这有帮助...
试试这个,我用过它,它有效而且简单
<div class="fixed-css1 fixed-css2 @(Class)">
some child content...
</div>
我不确定这是否是一个不好的做法,
它会阻止 itellisense 在类属性中正常工作,
但这很容易工作,只需将其添加到属性的最后
,如果您需要使用智能感知进行更改,请在@(类)之前添加一个“”,进行更改,然后删除“”
如果组件上未设置 Class 参数,则可能会在类字符串中留下空格
例如
<div class="fixed-css1 fixed-css2 ">
(末尾有空格)您可以通过两种方式做到这一点。
第一种方法,您可以使用字典从父级传递给子级,如下所示。我在此示例中添加了
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-centric-attributes/
假设:
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>
你的模式很好,但可以简化一点。
<div class="fixed-css1 fixed-css2 @Class">
some child content...
</div>
@code
{
[Parameter]
private string Class { get; set; } = "";
}
@Class
将打印变量的内容,即附加到组件的类,并且它可以在现有字符串的末尾执行此操作。