【问题标题】:How to change classes of a div element using Blazor如何使用 Blazor 更改 div 元素的类
【发布时间】:2019-06-02 21:55:09
【问题描述】:

我在cshtml页面中有一个典型的div元素,格式如下:

<div id="loginErrors" class="alert alert-danger hide-errors">@(ErrorMessage)</div>

在 Blazor 之前,我通常使用 jQuery 从 div 中添加或删除 hide-errors 类。但是,Blazor 正在尝试消除对 JavaScript 的需求,并且我正在尝试使用尽可能少的 JSInterop。 Blazor 中有没有办法做到这一点?

所以在 Blazor 中我可以这样做:

 @if (!string.IsNullOrEmpty(ErrorMessage))
 {
     <div id="loginErrors" class="alert alert-danger">@(ErrorMessage)</div>
 }
 else
 {
     <div id="loginErrors" class="alert alert-danger hide-errors">@(ErrorMessage)</div>
 }

或使用 JSinterop:

呼吁移除:

await JSRuntime.Current.InvokeAsync<object>("blazorExtensions.RemoveClass", "loginErrors", "hide-errors");

函数通常在哪里:

RemoveClass: function (id, classname) {
    var tt = '#' + id;
    $(tt).removeClass(classname);
}

与添加类类似。上述两种方法都有效,但如前所述。我试图避免 JSInterop 路线,我不喜欢 div 元素被声明两次,即使只有一个会进入 DOM。

【问题讨论】:

    标签: blazor


    【解决方案1】:

    就像你在普通 Razor 中所做的那样:

    @if (price>30)
    {
        <p>The price is too high.</p>
    }
    

    编辑 对于更新的问题,我猜你想要这个:

    <div class="@((string.IsNullOrEmpty(ErrorMessage)? "hide-errors" : ""))">
    

    【讨论】:

    • 我试图避免 if else 场景并声明了 2 个具有相同 id 的 div 元素,一个具有类 hide-errors 一个没有。因此,我确实想实际删除或添加类
    • 好的。但是你问题中 else 的目的是什么?它没有添加任何功能..
    • 那你为什么需要一个ID?
    • 我们有 ID,因为 Specflow 需要 ID
    【解决方案2】:

    这非常简单,因为您可以在 Blazor 中动态更改 html 元素的任何部分,无需使用 Javascript。经过这么多年,我承认,我花了一点时间才摆脱旧的 Javascript 思维方式,但一旦你这样做了,Blazor 就会摇滚!

    在您的 html 某处,使用一个变量作为您想要对其进行动态样式(或其他)修改的任何 html 元素的类名(或其他属性)。

        <img class="@myImageClass" src="@myImg" />
    

    在@functions 中声明你创建的任何变量...

        @functions {
        string myImageClass { get; set; }
        string myImg { get; set; } // Swap out the image as well if you want. 
    

    如果您想将项目设置为最初使用 OnInit()

         protected override void OnInit()
         {
         myImageClass = "myImageVisible";
         myImg = "https://www.somesite.com/ImageToStartWith.png"
    
         }
    

    函数中的某处将所需的类更改为您在样式部分中预定义的内容。

        private async Task DoSomething()
        {
          myImageClass = "myImageHidden";
          myImg = "https://www.somesite.com/NewImageToSwapIn.png"
          //Not sure what the point of swapping an image on a hidden element is 
          //but you get the idea. You can change anything you want anytime. 
        }
    

    不要忘记预先定义一些你想使用的样式。

         <style>
         .myImageVisible {
          display: block;
          }
    
         .myImageHidden{
          display: none;
          }
          </style>
    

    享受。 :)

    【讨论】:

    • 对于每个编辑表单中有 25 个以上字段的 LOB 应用程序来说,它并没有真正发挥作用,您必须在视图模型中处理 3-4 倍的属性数量。想想看。您需要一个用于实际数据的属性,一个用于 css 类的属性,一个用于 disabled 属性的属性,一个用于 tabindex 的属性……等等。与 JS 相比,您只需获取 ID 并直接设置属性,无需将其保存在扩展视图模型中。
    • @LinusProxy 这就是 Blazor 组件的用武之地,您可以通过层次结构执行其中的一些操作。您还可以使用 HTML5/CSS3 解决其中一些类型的问题,而无需执行任何 Blazor (C#) 或 JavaScript。在这个特定示例中,可以使用 CSS3 过渡(无需 JS/C#)。
    【解决方案3】:

    为完全的怪胎(我)创建一个剃须刀组件(xaml 爱好者的梦想):

    示例用法

    <ContentView Size="Small" IsVisible="@IsOnline">
    
     <img src="@myImg" />
    
    </ContentView>
    

    结果:应用了适当类的 div,class='size-small' 对应于 Size="Small"

    您可以向此类组件添加任何参数并根据您的逻辑更改内部的类,从而保持主页清洁。

    ContentView.razor

    @if (IsVisible)
        {
        <div class="@sizeClass"> @ChildContent</div>
        }
    
    @code {
    
    
        [Parameter]
        public RenderFragment ChildContent { get; set; }
    
        [Parameter]
        public bool IsVisible { get; set; } = true;
    
        [Parameter]
        public string Size {
            get
            {
                return _size.ToString();
            }
            set
            {
                _size = Enum.Parse<MySize>(value);
                switch (_size)
                {
                    case MySize.Big:
                        sizeClass = "size-big";
                        break;
                    case MySize.Small:
                        sizeClass = "size-small";
                        break;
                    default:
                        sizeClass = "";
                        break;
                }
            }
        }
    
        private MySize _size;
    
        private string sizeClass;
    
        public enum MySize
        {
            Default,
            Small,
            Big
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      这是我在控制特定元素的 UI(例如突出显示单击的元素)的上下文中问自己的一个问题,以防它们中有很多,例如列表。

      两种常见的方式(正如其他人提到的)是:

      1. 在元素class="@someProp some-other-class..."属性中绑定一个页面/组件字符串属性,可以用来设置多个类(因为它只是一个字符串)或添加多个此类属性(用于更精细的条件控制)。
      2. 创建一个专用组件,其中包含将类或 CSS 值绑定到的所有必需属性。

      但我想我想出了第三种方式,一种“介于两者之间”的技术,它提供了一个非常强大的带有对象绑定(甚至是 2 路绑定)的 UI 控件,而无需处理单独的组件。因为有时候需要手动触发父组件StateHasChanged(),比如父子组件之间存在各种依赖,而视觉状态机制却没有自动刷新。

      只需创建一个包装类,用您想要控制的 CSS 值作为其属性来表示项目。在同一页面/组件 @code 部分或某个共享文件夹中。

      例如,我有一个 Slide 对象列表,由 卡片 直观地表示(并因此包装) em> 对象,用户可以点击它来选择和编辑。

      项目模型:

      public class Slide {
         public int SlideId { get; set; }
         public string Title { get; set; }
         public string Description { get; set; }
         public int SortIndex{ get; set; }
      }
      

      项目包装模型:

      public class Card {
         Slide Slide { get; set; }
         public string SelectedCssClass { get; set; }
         public string SomeOtherCssClass { get; set; }
         
         public void Reset() {
            SelectedCssClass = "";
         {
      }
      

      所以在组件初始化期间,在 OnIntialized() 方法(或 OnInitializedAsync() 如果您获取并等待数据列表)我用一个新的包装器对象包装每个项目。然后在 @foreach() { } 循环中,列出包装的项目,我附加一个 @onclick 事件处理程序到每个 div/card,传递该卡对象的引用:

      @foreach (Card card in Cards)
      {
         <div class="card @card.SelectedCssClass" @onclick="@(e => setSlideToEdit(card))"
      }
      

      setSlideToEdit(card) { } 函数中,我可以通过简单地调用 来重置先前选择的幻灯片的样式(存储在某些属性中) card.Reset() 方法并让绑定完成工作,然后使用新的并将 card.SelectedCssClass 属性设置为我的希望(或添加另一种专用方法来设置预定义的方法)。

      【讨论】:

        猜你喜欢
        • 2020-08-22
        • 1970-01-01
        • 2011-07-09
        • 2010-09-16
        • 1970-01-01
        • 2020-12-13
        • 2012-01-24
        相关资源
        最近更新 更多