【问题标题】:CSS isolation in blazor doesn't work with predefined Form elementsblazor 中的 CSS 隔离不适用于预定义的表单元素
【发布时间】:2021-01-25 18:48:27
【问题描述】:

我有一个页面 foo.razor,它代表一个表单:

<EditForm Model=SomeModel>
    <InputText @bind-Value=SomeModel.Property1 />
    <InputText @bind-Value=SomeModel.Property2 />
    <p>a paragraph</p>
</EditForm>

在它旁边我有一个独立的 CSS,foo.razor.css,例如:

input{
  display: block;
}
p{
  color: lime;
}

段落的样式正确应用,但输入元素的样式不正确。我不明白为什么。

另外,我知道 blazor 会在编译后为元素生成随机 id。在浏览器中,我可以看到该段落有这样的 id,但输入和表单元素也没有。

我尝试为组件添加类名并使用深度选择器,如下所示:

::deep .classname {
  .......
}

但这也不起作用。

【问题讨论】:

    标签: blazor blazor-client-side blazor-webassembly


    【解决方案1】:

    CSS 隔离的棘手之处在于它只适用于纯 HTML 节点,不适用于组件。在幕后,定义隔离 CSS 的当前组件中的元素会获得一个自定义(某种随机)属性,并且 CSS 规则通过该属性级联以限定到您当前的组件。框架不知道其他组件内部是什么,因此它无法向它们添加该属性-它们的呈现是它们自己的。因此,这些作用域 CSS 规则不能针对组件。

    如何解决这个问题 - 将您的组件包装在当前组件的 HTML 元素中,并将规则写入该容器内的目标元素,方法是将该元素替换为 ::deep

    这是一个例子:

    input,
    ::deep input{
        display: block;
        border: 2px solid red;
    }
    
    p,
    ::deep p {
        color: lime;
        border: 2px solid red;
    }
    

    下面是修改表单的方法

    <EditForm Model=SomeModel>
        <div> @* This div right here is the "magic" *@
            <InputText @bind-Value=SomeModel.Property1 />
            <InputText @bind-Value=SomeModel.Property2 />
            <p>a paragraph</p>
        </div>
    </EditForm>
    
    @code{
        TestModel SomeModel { get; set; } = new TestModel();
        public class TestModel
        {
            public string Property1 { get; set; }
            public string Property2 { get; set; }
        }
    }
    

    【讨论】:

    • 太棒了。谢谢。我还发现了这个issue,它描述了你刚才提到的技巧。
    【解决方案2】:

    @rdmptn 的答案是正确的,但无论如何我都会加两分钱。我努力了很长时间来理解并让::deep 工作,我将分享我的旅程。

    假设我们想覆盖子组件中&lt;p&gt; 标记的颜色:

    MyComponent.razor.css

    ::deep p { color: red !important; }
    

    MyComponent.razor:

    <span>My component!</span>
    <OtherComponent/>
    

    OtherComponent.razor:

    <p>Other component!</p>
    

    现在,为 MyComponent.razor 生成的 HTML 类似于:

    <span random1="">My component!</span>
    <p random2="">Other component!</p>
    

    每个 .razor 组件都有一个随机的、唯一的组件 ID,它被分配给它的所有 纯 HTML 标签,即&lt;div&gt;&lt;p&gt;&lt;span&gt;&lt;img&gt; 等. 注意MyComponent 中的&lt;span&gt; 元素是如何被random1 标记的。同样,&lt;p&gt; 元素被标记为 random2,因为该元素是在 OtherComponent 中定义的。

    但是从 MyComponent.razor.css 生成的 CSS 看起来像:

    [random1] p { color: red !important; }
    

    也就是说,::deep CSS 选择器变成类似于“所有类型的元素 &lt;p&gt; 在带有标签的元素下 random1”。从上面生成的 HTML 中,很明显这与 OtherComponent 中的 &lt;p&gt; 不匹配。这就是为什么将内容包装在 &lt;div&gt; 中的原因:

    MyComponent.razor(更新)

    <span>My Component!</span>
    <div>
        <OtherComponent/>
    </div>
    

    还有新生成的 HTML:

    <span random1="">My Component!</span>
    <div random1="">
      <p random2="">Other component!</p>
    </div>
    

    现在::deep CSS 选择器将匹配 OtherComponent 中的&lt;p&gt; 标签。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 2021-02-20
      • 2021-03-01
      • 2021-05-01
      相关资源
      最近更新 更多