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

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

字面量、表达式和指令

源代码[1]

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

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

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

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

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

1d9f71c4b507ac696b8e22ab757832c4.gif

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

<MyComponent Value=@SomeValue/>
<MyComponent Value="@SomeValue"/>

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

字面量

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

类型Razor 视图HTML
HTML 属性<input size=8/><input size=”8″/>
组件参数<MyHeader Text="Hello" Visible=true/><h1>Hello</h1>

MyHeader 的定义如下:

@if (Visible)
{<h1>@Text</h1>
}@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
<input size=@InputSize/><input size=”8″/>
<input size=@DoubleInputSize()/><input size=”16″/>
<MyHeader Text=@HeaderText Visible=@HeaderVisible/><h1>Value of variable</h1>

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

Razor 视图HTML
<input size=@(InputSize * 3) /><input size=”24″/>
<input value=@($"Size is {InputSize}") /><input value=”Size is 8″/>
<input value=@($"Size is {DoubleInputSize()}") /><input size=”Size is 16″/>

计算为复杂类型的表达式

复杂类型也可以作为参数值传递给 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() 方法来表示该值。

<div class="row"><div class="col-4">To HTML attribute using .ToString()</div><div class="col-8"><input readonly value=@MyPerson /></div>
</div>@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 如下:

<div class="row"><div class="col-4">To HTML attribute using .ToString()</div><div class="col-8"><input readonly value="Mr Peter Morris" /></div>
</div>

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

<div class="row"><div class="col-2">Salutation</div><div class="col-10">@Person?.Salutation</div>
</div>
<div class="row"><div class="col-2">Given name</div><div class="col-10">@Person?.GivenName</div>
</div><div class="row"><div class="col-2">Family name</div><div class="col-10">@Person?.FamilyName</div>
</div>
@code
{[Parameter]public Person Person { get; set; }
}
  • 第 14-15 行

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

  • 第 3、7 和 10 行

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

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

<div class="row"><div class="col-4">To component as object</div><div class="col-8"><PersonView Person=@MyPerson /></div>
</div>

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

ef3ba08b38ea390b27161efcf2c88db2.png

推断表达式

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

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

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

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

标记C#
<MyComponent Visible=”true“/>Visible = true
<MyComponent Visible=@HeaderVisible/>Visible = HeaderVisible
<MyComponent Visible=”HeaderVisible“/>Visible = HeaderVisible

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

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

标记C#
<MyComponent Text=”Hello”/>Text = “Hello”“Hello”
<MyComponent Text=@HeaderText/>Text = HeaderText“Value of variable”
<MyComponent Text=”HeaderText”/>Text = “HeaderText”“HeaderText”
<MyComponent Text=HeaderText/>Text = “HeaderText”“HeaderText”
  • 第一个例子是明确的,在我们的使用组件中没有名为 Hello 的成员,因此编译器知道我们打算将 Text 设置为文字字符串。

  • 第二个例子也很明确,因为我们已经通过在我们的值之前添加一个 @ 符号来明确地确定这是一个表达式。

  • 第三个示例不明确,因为我们有一个名为 HeaderText 的成员。Blazor 必须确定这是文字字符串还是表达式。

  • 第四个示例可能看起来像一个明确的成员引用,但由于 HTML 和 Blazor 都支持传递不带引号的值,因此这很容易成为不带引号的文字字符串。

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

  • <MyHeader Text=HeaderText Visible=HeaderVisible/>

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

  • <MyHeader Text=@HeaderText Visible=”HeaderVisible“/>

两者都是表达。

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

9eca75a5b05a4447980d70f3788d2e73.gif

指令

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

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

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

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

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

// Razor mark-up with @ref directive
<h1 @onclick=H1Clicked>Hello, world!</h1>@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<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, H1Clicked));__builder.AddContent(2, "Hello, world!");__builder.CloseElement();}
}
  • 第 2 行

    使用 @onclick 指令定义 H1 元素。

  • 第 18 行

    显示如何转换 @onclick=H1Clicked 指令,以便在呈现的元素上设置 DOM onclick 事件。

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

  • @code

    此指令标识应按原样输出到生成的 C# 文件中的 C# 代码块。单个 Razor 标记文件中可以有多个 @code 指令;Blazor 会将这些整理到转译文件中的单个 C# 代码块中。

  • @page

    此指令在转译的类上生成一个 [PageAttribute],使 Blazor 路由[6](稍后介绍)能够识别在 URL 中给定特定地址的情况下要呈现哪个组件(页面)。

  • @layout

    在转译的类上生成 [LayoutAttribute]。Blazor 使用它来确定使用哪个布局(如果有)来包装页面的内容。

  • @typeparam

    指示 Blazor 从 Razor 标记生成泛型类。

  • @inject

    允许组件指定 Blazor 在创建组件的新实例时需要注入的依赖项。

  • @attribute

    将指定的 DotNet 属性添加到生成的 C# 类。

以下是一组可应用于当前 Razor 文件正在使用的组件和 HTML 元素的指令示例。例如 <h1 @ref=MyH1Element>Hello</h1>

  • @ref

    标识当前组件的成员或属性,该成员或属性应包含对将呈现的 HTML 元素或组件的引用。在使用 JavaScript 互操作时,这些可以用作引用,或者获取对 Blazor 嵌入组件的引用,以便我们可以在其上调用方法。

  • @bind

    允许我们将数据绑定(双向绑定)到正在使用的组件的属性或 HTML 元素的属性。

  • @attributes

    将名称-值[7]对作为 HTML 属性输出。

  • @key

    使我们能够为元素/组件提供唯一标识符,这有助于在渲染[8] HTML 时保持较小的更改增量。

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

  • @onmousemove

  • @onclick

  • @onkeypress

  • @onscroll

指令属性

源代码[10]

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

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

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

<html><body><div onclick="console.log('Top level clicked')"><h1>Top level</h1><div onclick="console.log('Second level clicked')"><h2>Second level</h2><div onclick="console.log('Third level clicked')"><h3>Third level</h3></div></div></div></body>
</html>

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

f8db3ccba50c29b1315c37e8ccf23024.png

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

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

@page "/"
@using System.Diagnostics<div @onclick=TopLevelClicked><h1>Top level</h1><div @onclick=SecondLevelClicked @onclick:stopPropagation><h2>Second level</h2><div @onclick=ThirdLevelClicked><h3>Third level</h3></div></div>
</div>@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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET6之MiniAPI(二十七):Metrics

应用的各种Metrics是保证应用健康稳定运行的基础&#xff0c;特别对于一些可用性有所要求的应用&#xff0c;本文介绍prometheus-net这个三方指示库。prometheus-net的工作原理是&#xff0c;在应用内部埋点&#xff0c;通过prometheus采集数据&#xff0c;然后通过grafana把采…

回溯算法之布罗夫卫队(最大团问题)

1、问题 在原始部落中,由于食物缺乏,部落居民经常因为争夺猎物发生冲突,几乎每个居民都 有自己的仇敌。部落酋长为了组织一支保卫部落的卫队,希望从居民中选出最多的居民加入 卫队,并保证卫队中任何两个人都不是仇敌。假设已给定部落中居民间的仇敌关系图,编程 计算构建部落护…

microdot - 一个开源 .NET 微服务框架。

简介Microdot 是一个开源 .NET 框架&#xff0c;可满足轻松创建微服务的许多需求。它的一些主要特点•用于托管微服务的服务容器•服务间 RPC&#xff0c;便于基于接口的服务通信•服务之间的客户端透明响应缓存•日志记录和分布式跟踪支持•客户端负载均衡和服务发现•详细的健…

slider控件控制文本框字体大小

1.控件代码 <pre name"code" class"csharp"> <Slider x:Name"slider1" HorizontalAlignment"Left" Margin"0,261,0,0" VerticalAlignment"Top" Width"446" ValueChanged"Slid…

争时金融java_Java高并发编程基础之AQS

引言曾经有一道比较比较经典的面试题“你能够说说java的并发包下面有哪些常见的类&#xff1f;”大多数人应该都可以说出CountDownLatch、CyclicBarrier、Sempahore多线程并发三大利器。这三大利器都是通过AbstractQueuedSynchronizer抽象类(下面简写AQS)来实现的&#xff0c;所…

Xamarin效果第十三篇之弹窗PopupPage

在上一篇文章中使用Xamarin实现控制了一下祖传的PLC;基本的功能也就完事了,这不总觉得少点最基本的配置;那就趁着激情还在赶紧再去完善一下,不然激情已过就懒得去摸索了;来看看最终咱实现的视频效果:1、关于弹窗,直接使用开源的PopupPageInstall-Package Rg.Plugins.Popup -Ver…

C# 线程问题之争用条件

用多个线程编程并不容易。在启动访问相同数据的多个线程时&#xff0c;会间歇性地遇到难以发现的问题。如果使用任务、并行 LINQ 或 Parallel 类&#xff0c;也会遇到这些问题。为了避免这些问题&#xff0c;必须特别注意同步问题和多个线程可能发生的其他问题。下面探讨与线程…

尾调用优化 java_为什么JVM仍然不支持尾调用优化?

拉丁的传说也许您已经知道这一点&#xff0c;但是这个功能并不像听起来那么简单&#xff0c;因为Java语言实际上将堆栈跟踪暴露给程序员。考虑以下程序&#xff1a;public class Test {public static String f() {String s Math.random() > .5 ? f() : g();return s;}publ…

【AngularJS】—— 2 初识AngularJs(续)

前一篇了解了AngularJS的一些简单的使用&#xff0c;这里继续跟着w3c学习一下剩下的内容。 本篇根据w3cschool.cc继续学习AngularJS剩余的内容&#xff0c;包括&#xff1a; 1 事件 2 模块 3 表单 4 数据验证 5 bootstrap CSS风格 6 include包含其他页面 7 应用程序 8 参考手册…

特斯拉为何使用.NET 技术栈?

【精选转载】| 来源/知乎在知乎上有一个帖子非常热闹&#xff1a;“为何特使拉使用.net core技术栈 而不用 java&#xff1f;”1回答1&#xff1a;Kasim作者&#xff1a;Kasim链接&#xff1a;https://www.zhihu.com/question/496204534/answer/2269157872这题我熟啊&#xff0…

Blazor University (6)组件 — 组件事件

原文链接&#xff1a;https://blazor-university.com/components/component-events/组件事件源代码[1]EventCallback<T> 类是一个特殊的 Blazor 类&#xff0c;可以作为参数公开&#xff0c;以便组件可以在发生感兴趣的事情时轻松通知使用者。一旦声明了 EventCallback&l…

Xamarin效果第十四篇之玩耍GIS

最近再次拾起Xamarin然后也实现了祖传PLC控制和弹窗配置;这不又一次勾起来我想基于他玩玩原来一直玩耍的GIS,毕竟咱前面一直玩耍二维和三维的GIS相关的知识点;有兴趣的小伙伴可以翻翻我的历史文章;趁着激情满满;来看看最终咱实现的加载高德平面地图效果(有水印):再者就是满足群…

PHP进程退出信号_一文吃透 PHP 进程信号处理

背景前两周老大给安排了一个任务&#xff0c;写一个监听信号的包。因为我司的项目是运行在容器里边的&#xff0c;每次上线&#xff0c;需要重新打包镜像&#xff0c;然后启动。在重新打包之前&#xff0c;Dokcer会先给容器发送一个信号&#xff0c;然后等待一段超时时间(默认1…

GitHub Copilot 现已登陆 Visual Studio!

激动人心的好消息来了&#xff0c;GitHub 在3月29日发布博客&#xff0c;宣布 Github Copilot 现在可以在 Visual Studio 中使用。我们知道 Visual Studio 的 IntelliCode 本身已经很智能了, 现在又迎来了 Copilot, 编程体验将进入新的篇章。如何安装? 首先&#xff0c;您…

iOS 9音频应用播放音频之音量设置与声道设置

iOS 9音频应用播放音频之音量设置与声道设置 iOS 9音频应用音量设置 音量又称响度、音强&#xff0c;是指人耳对所听到的声音大小强弱的主观感受&#xff0c;其客观评价尺度是声音的振幅大小。在iOS 9音频应用的应用中&#xff0c;经常会出现播放的音乐音量过大或者过小。此时i…

php fpm工作原理,什么是phpfpm的工作原理?

什么是phpfpm的工作原理&#xff1f;发布时间&#xff1a;2020-07-13 15:12:53来源&#xff1a;亿速云阅读&#xff1a;181作者&#xff1a;Leah什么是phpfpm的工作原理&#xff1f;针对这个问题&#xff0c;这篇文章详细介绍了相对应的分析和解答&#xff0c;希望可以帮助更多…

C#对象映射器之Mapster

简介Mapster是一个快&#xff0c;小巧&#xff0c;功能强大的对象映射.Net框架例子我有两个Model类且他们的属性一致&#xff0c;我们将 SourceObjectTest赋值给DestObjectTest该怎么做&#xff1f;SourceObjectTest sourceObject new SourceObjectTest(); sourceObject.Name …

如何关闭Struts2的webconsole.html

出于安全目的&#xff0c;在禁用了devMode之后&#xff0c;仍然不希望其他人员看到webconsole.html页面&#xff0c;则可以直接删除webconsole.html 的源文件&#xff0c; 它的位置存在于&#xff1a; 我们手工删除 struts2-core-*.jar\org\apache\struts2\interceptor\debuggi…

UIView 的基础

UIView•什么是控件&#xff1f;-屏幕上的所有UI元素都叫做控件&#xff0c;也有人叫做视图、组件-按钮&#xff08;UIButton&#xff09;、文本&#xff08;UILabel&#xff09;都是控件•控件的共同属性有哪些&#xff1f;-尺寸-位置-背景色-......-•苹果将控件的共同属性都…

JS

为什么80%的码农都做不了架构师&#xff1f;>>> function getQueryString(name) {var reg new RegExp("(^|&)" name "([^&]*)(&|$)"),r window.location.search.substr(1).match(reg);if(r ! null) {return unescape(r[2]); }r…