Blazor University (5)组件 — 字面量、表达式和指令

原文链接:https://blazor-university.com/components/literals-expressions-and-directives/

字面量、表达式和指令

源代码[1]

请注意,本节一般不涵盖 Razor 标记。它不会涵盖诸如条件输出、循环等内容。该主题在网络和书籍中的其他地方得到了广泛的介绍。

使用组件时,我们可以将信息作为参数传递。这些参数可以是简单类型,例如整数、字符串、布尔值,也可以是复杂类型,例如 Func、Action 或复杂对象的实例。与 HTML 属性不同,我们不限于可以在纯 HTML 文件中表示为值的值。

Blazor 如何解释我们传递给组件的值取决于我们正在设置的 [Parameter] 的类型,以及我们是否通过使用 @ 符号明确了我们的意图。

参数使用 name=value 格式分配,就像它们在 HTML 标记中一样。我们是否使用表达式来确定值、指令(一种特殊情况)或文字取决于 @ 符号的位置(或不存在)。

位置 类型 示例
不存在 字面量
表达式
指令
记住这一点的一个简单方法是“灯泡法”。我们从右到左拼出缩写 L.E.D[2]

Blazor University (5)组件 — 字面量、表达式和指令_第1张图片

与 HTML 标记一样,Blazor 标记允许我们选择是否希望将值括在引号中。以下是等价的。


我个人的偏好是仅在传递文字字符串时才将参数值括在引号中。

字面量

任何传递给 HTML 属性的值(不以 @ 开头)都被视为字面量。将值传递给 Blazor 组件上的 [Parameter] 修饰属性时,情况并非总是如此(我将在此处[3]详细介绍),但在大多数情况下,此规则适用。

类型 Razor 视图 HTML
HTML 属性
组件参数

Hello

MyHeader 的定义如下:

@if (Visible)
{
  

@Text

} @code {   [Parameter]   public bool Visible { get; set; } = true;   [Parameter]   public string Text { get; set; } }

除了推断表达式[4](仅适用于组件上的参数,而不适用于 HTML 属性)之外,在渲染组件时,您在 HTML 中看到的内容实际上就是您在标记中编写的内容。

表达式

当我们需要渲染包含动态值而不是固定文字值的 HTML 时,我们需要使用表达式。我们通过在我们分配的值之前添加 @ 符号来向 Blazor 表明我们正在使用表达式。然后,Blazor 将尝试将 @ 后面的文本解释为一段有效的 C# 代码,例如成员名称或方法调用。

给定我们组件中定义以下成员和值的代码部分:

int InputSize = 8;
bool HeaderVisible = true;
string HeaderText = "Value of variable";

private int DoubleInputSize()
{
  return InputSize * 2;
}

我们希望看到以下内容:

Razor 视图 HTML

Value of variable

我们甚至可以通过将表达式文本括在括号中来传递更复杂的表达式,例如字符串插值和/或计算值。

Razor 视图 HTML

计算为复杂类型的表达式

复杂类型也可以作为参数值传递给 HTML 属性和 Blazor 组件的 [Parameter] 属性。将非简单值作为表达式传递给 HTML 属性时,Blazor 将使用 ValuePassed.ToString() 呈现该值;当值被传递到 Blazor 组件上的 [Parameter] 属性时,对象本身被传递。

以下面的 Person 类为例:

public class Person
{
  public string Salutation { get; set; }
  public string GivenName { get; set; }
  public string FamilyName { get; set; }

  public override string ToString() => $"{Salutation} {GivenName} {FamilyName}";
}

如果我们在其中一个视图中创建 Person 的实例,我们可以将该实例作为值传递给标准 HTML 属性,并且 Blazor 将使用重写的 ToString() 方法来表示该值。


  To HTML attribute using .ToString()
  
@code {   Person MyPerson;   protected override void OnInitialized()   {     base.OnInitialized();     MyPerson = new Person     {       Salutation = "Mr",       GivenName = "Peter",       FamilyName = "Morris"     };   } }
  • 第 8 行 声明 Person 类型的成员

  • 第 13 行 创建 Person 的实例

  • 第 3 行将 Person 实例作为 HTML 属性传递

呈现的 HTML 如下:


  To HTML attribute using .ToString()
  

要证明 Blazor 通过引用其他组件来传递对象,请创建一个将 Person 实例作为 [Parameter] 的新组件。创建一个名为 PersonView 的新组件并输入以下标记:


  Salutation
  @Person?.Salutation
  Given name
  @Person?.GivenName   Family name   @Person?.FamilyName @code {   [Parameter]   public Person Person { get; set; } }

声明一个名为 Person 的属性,该属性是 Person 类型,并使用 [Parameter] 属性对其进行装饰,以便任何使用组件都可以在 Razor 标记中设置其值。

如果 Person 不为 null,则会显示 Salutation、GivenName 和 FamilyName。

最后,更改我们的视图,使其将 MyPerson 传递给我们的新 PersonView 组件:


  To component as object
  
    
  

运行应用程序时,我们现在可以看到将 MyPerson 传递给 HTML 属性的结果,以及作为 Person 的实例传递给另一个 Blazor 组件的结果。

Blazor University (5)组件 — 字面量、表达式和指令_第2张图片

推断表达式

将字面量传递给使用组件的参数时,Blazor 需要确保传递的值与目标兼容。例如,给定具有布尔参数 Visible 的组件 MyHeader,以下组合是有效的。

标记 结果
表达式为真。
引号中的表达式。
字符串类型的文字,推断为表达式@true。
不带引号的文字字符串,再次推断为表达式@true。

该表的第一行是一个显式表达式,true。其他行实际上是在尝试将布尔参数设置为字符串值。在这些情况下,Blazor 将推断我们的意图并改为传递布尔值。

除非分配的属性是字符串,否则 Blazor 将取消引用作为参数传递给其他组件的值,并假定它们是表达式。下表显示了标记以及该标记如何转换为 C#。

标记 C#
Visible = true
Visible = HeaderVisible
Visible = HeaderVisible

在分配的属性是字符串的情况下,Blazor 将假定没有 @ 分配的值是字面量。

假设我们的使用组件有一个成员 string HeaderText = "Value of variable",并且嵌入组件有一个 [Parameter] 修饰属性 public string Text { get; set; } 下表显示了标记以及如何将其转换为 C#。

标记 C#
Text = “Hello” “Hello”
Text = HeaderText “Value of variable”
Text = “HeaderText” “HeaderText”
Text = “HeaderText” “HeaderText”

在 Visual Studio 中很容易看到 Blazor 如何解释分配。表达式是突出显示的语法,而文字则不是。

HeaderText 是一个文本字符串,HeaderVisible 是一个表达式。

两者都是表达。

为了避免意外地被推断的字面量绊倒,我的建议是坚持使用灯泡方法。始终通过在表达式前面加上 @ 符号来明确表达式。

Blazor University (5)组件 — 字面量、表达式和指令_第3张图片

指令

指令是内置宏,可更改从 Razor 标记生成的已转译 C# 代码。通过在标识符前面加上 @ 符号来使用指令,标识符是我们通常期望的 HTML 属性的名称或组件属性的名称。如果您还没有这样做,请阅读字面量、表达式和指令[5]

注意: 目前,与 Angular 等其他框架不同,Blazor 不允许开发人员创建自己的指令。

因为分配给指令的值的类型是已知的(它在 C# 代码中是强类型的),所以值将被推断为一个表达式。因此,与组件属性一样,在赋值的开头添加 @ 是不必要的,除非我们希望将表达式传递给需要字符串值的指令。一个例外是当我们希望传递一个 lambda 时;lambda 必须用 @ 符号转义并用括号括起来。

@onclick=@( args => Debug.WriteLine("Clicked") )

以下代码显示了如何使用 @onclick 指令将 DOM onclick 事件添加到呈现的 H1 元素。

// Razor mark-up with @ref directive
Hello, world!

@code
{
  public void H1Clicked(MouseEventArgs args)
  {
    System.Diagnostics.Debug.WriteLine("H1 clicked");
  }
}

// Transpiled C#
public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
{
  protected override void BuildRenderTree(RenderTreeBuilder __builder)
  {
    __builder.OpenElement(0, "h1");
    __builder.AddAttribute(1, "onclick", EventCallback.Factory.Create(this, H1Clicked));
    __builder.AddContent(2, "Hello, world!");
    __builder.CloseElement();
  }
}

适用于 Razor 文件本身的一些标准指令是:

以下是一组可应用于当前 Razor 文件正在使用的组件和 HTML 元素的指令示例。例如

Hello

以下是可用的 HTML DOM 元素事件的子集。这些将在组件事件[9]中更详细地讨论。

指令属性

源代码[10]

指令属性允许我们将附加信息传递给指令。如果我们将指令视为一个类,那么指令属性就是它的成员。

要传递这些附加信息,我们需要重复指令,然后附加一个 : 后跟指令支持的属性名称。

例如,默认情况下,我们的浏览器会将元素的事件向上传播,直到它最终到达 HTML 文档本身。一个普通的 HTML + JavaScript 演示将在单击元素时将文本输出到控制台。


  
    
      

Top level

               

Second level

                   

Third level

                       

因为 div 元素是嵌套的,所以当其中一个被点击时,该事件不仅会触发 div 本身的 onclick 代码,还会触发其父 div 上的 onclick,而父元素又会触发其自己的父级上的事件 – 以此类推,直到当前元素没有父元素。

Blazor University (5)组件 — 字面量、表达式和指令_第4张图片

单击第三级标题时的控制台输出

为了防止事件在元素树上传播,JavaScript 在事件上有一个 stopPropagation 方法[11]。Blazor 使用指令属性防止传播 - @onclick:stopPropagation

@page "/"
@using System.Diagnostics


  

Top level

       

Second level

           

Third level

        @code {   private void TopLevelClicked()   {     Debug.WriteLine("Top level clicked");   }   private void SecondLevelClicked()   {     Debug.WriteLine("Second level clicked");   }   private void ThirdLevelClicked()   {     Debug.WriteLine("Third level clicked");   } }

第 4、6 和 8 行都定义了 @onclick 属性,并声明了触发浏览器 onclick 事件时要执行的 C# 方法。第 6 行添加了一个额外的 @onclick:stopPropagation 以防止浏览器将点击从第二级传播到第一级。更多 DOM 事件将在关于 DOM 事件的部分中介绍。

一些指令属性期望我们以 @directive:attribute="value" 的形式指定一个值。我们将在双向绑定[12]一节中详细介绍这一点。

参考资料

[1]

源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/Components/LiteralsExpressionsAndDirectives

[2]

L.E.D: https://en.wikipedia.org/wiki/Light-emitting_diode

[10]

源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/Components/DirectiveAttributes

[11]

stopPropagation 方法: https://www.w3schools.com/jsref/event_stoppropagation.asp

你可能感兴趣的:(c#,java,javascript,vue,python)