ASP.NET Core的"asp-fallback-*"CDN标记助手如何工作?

lon*_*nix 14 c# razor asp.net-core asp.net-core-tag-helpers asp.net-core-2.1

我理解asp-fallback-*标签助手的作用.我不明白的是如何.

例如:

<link rel="stylesheet"
      href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css"
      asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
      asp-fallback-test-class="sr-only"
      asp-fallback-test-property="position"
      asp-fallback-test-value="absolute" />
Run Code Online (Sandbox Code Playgroud)

这将从CDN加载引导程序,并在CDN关闭时加载本地副本.

但它如何决定呢?我认为它会检查asp-fallback-test-class,asp-fallback-test-propertyasp-fallback-test-value.但这些属性意味着什么?

如果我想从CDN上挂一些其他的库,我需要为那些提供一些东西,但我不知道该把它放在那里.

有很多这方面的例子,但是我找不到关于它是如何工作的解释.

更新
我并不是真的想了解标签助手的工作原理 - 它们是如何渲染的,等等.我试图了解如何为这些属性选择值.例如,jQuery回退脚本通常具有asp-fallback-test="window.jQuery"合理意义 - 它是测试jQuery是否已加载的测试.但是我上面展示的那些是完全不同的.如何选择它们?如果我想使用其他一些CDN交付的库,我需要为这些属性指定值...我会用什么?为什么选择那些引导程序?

更新2
要了解回退过程本身的工作原理以及这些标记的编写方式,请参阅@ KirkLarkin的回答.要了解使用这些测试值的原因,请参阅我的回答.

Kir*_*kin 14

TL; DR:

  • 一个<meta>标签添加到具有一个CSS类的DOM sr-only.
  • 将额外的JavaScript写入DOM,其中:
    1. 找到所述<meta>元素.
    2. 检查所述元素是否具有position设置为的CSS属性absolute.
    3. 如果没有这样的属性值被设置,一个附加<link>元件被写入到DOM用href~/lib/bootstrap/dist/css/bootstrap.min.css.

LinkTagHelper针对您的<link>元素运行的类<meta>在输出HTML中插入一个元素,该元素的CSS类为sr-only.元素最终看起来像这样:

<meta name="x-stylesheet-fallback-test" content="" class="sr-only" />
Run Code Online (Sandbox Code Playgroud)

生成元素的代码如下所示(源代码):

builder
    .AppendHtml("<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"")
    .Append(FallbackTestClass)
    .AppendHtml("\" />");
Run Code Online (Sandbox Code Playgroud)

不出所料,值的值FallbackTestClass是从属性中获得<link>asp-fallback-test-class.

插入此元素后,<script>还会插入相应的块().该代码的开头是这样的:

// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
// <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
// indicating that the primary stylesheet failed to load.
// GetEmbeddedJavaScript returns JavaScript to which we add '"{0}","{1}",{2});'
builder
    .AppendHtml("<script>")        
    .AppendHtml(JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName))
    .AppendHtml("\"")
    .AppendHtml(JavaScriptEncoder.Encode(FallbackTestProperty))
    .AppendHtml("\",\"")
    .AppendHtml(JavaScriptEncoder.Encode(FallbackTestValue))
    .AppendHtml("\",");
Run Code Online (Sandbox Code Playgroud)

这里有一些有趣的事情:

  • 评论的最后一行,指的是占位符{0},{1}{2}.
  • FallbackJavaScriptResourceName,表示输出到HTML的JavaScript资源.
  • FallbackTestProperty并且FallbackTestValue,分别从属性asp-fallback-test-propertyasp-fallback-test-value.

那么,让我们看一下JavaScript资源(源代码),它归结为具有以下签名的函数:

function loadFallbackStylesheet(cssTestPropertyName, cssTestPropertyValue, fallbackHrefs, extraAttributes)
Run Code Online (Sandbox Code Playgroud)

用我叫了早些时候的评论的最后一行和值相结合这个asp-fallback-test-propertyasp-fallback-test-value,我们可以推论,这是调用像这样:

loadFallbackStylesheet('position', 'absolute', ...)
Run Code Online (Sandbox Code Playgroud)

我不会深入研究fallbackHrefsextraAttributes参数,因为这应该是有点明显的,并且很容易自己探索.

实施loadFallbackStylesheet并没有太大的作用 - 我鼓励您自己探索完整的实施.这是来源的实际检查:

if (metaStyle && metaStyle[cssTestPropertyName] !== cssTestPropertyValue) {
    for (i = 0; i < fallbackHrefs.length; i++) {
        doc.write('<link href="' + fallbackHrefs[i] + '" ' + extraAttributes + '/>');
    }
}
Run Code Online (Sandbox Code Playgroud)

该脚本获取相关<meta>元素(假设它直接位于<script>自身上方)并简单地检查它是否具有position设置为的属性absolute.如果没有,<link>则为每个回退URL将其他元素写入输出.


lon*_*nix 6

好吧,我想我现在通过结合@KirkLarkin的答案和常识来得到它。

sr-only应用于隐藏meta元素。如果加载了引导程序,则该元素的CSS值将为position:absolute。因此已经过测试,如果是这样,则表明Bootstrap已加载。

因此,对于任何库,您都需要选择一个仅库可以执行的操作的良好示例,并相应地设置隐藏<meta>标签的样式,然后指定要测试的CSS样式以及期望的值。

对于javscript来说,它甚至更容易,因为您可以测试库本身,该库通常window在DOM或DOM中添加一些众所周知的变量。因此,对于jQuery而言,它是window.jQuery,对于Bootstrap而言,它可以进行测试window.jQuery && window.jQuery.fn && window.jQuery.fn.modal,依此类推。

  • 请注意,在 [bootstrap 5](https://getbootstrap.com/docs/5.1/migration/#helpers) 中,“sr-only”类已重命名为“视觉隐藏”。 (2认同)