【问题标题】:How do ASP.NET Core's "asp-fallback-*" CDN tag helpers work?ASP.NET Core 的“asp-fallback-*”CDN 标签助手如何工作?
【发布时间】:2018-12-24 02:06:32
【问题描述】:

我了解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" />

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

但它是如何决定这样做的呢?我假设它检查asp-fallback-test-classasp-fallback-test-propertyasp-fallback-test-value。但是这些属性是什么意思呢?

如果我想从 CDN 连接其他库,我需要为这些库提供一些东西,但我不知道该放什么。

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

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

更新 2
要了解回退过程本身是如何工作的,以及这些标签是如何编写的,请参阅@KirkLarkin 的回答。要了解为什么使用这些测试值,请参阅我的回答。

【问题讨论】:

    标签: c# asp.net-core razor asp.net-core-2.1 asp.net-core-tag-helpers


    【解决方案1】:

    TL;DR

    • &lt;meta&gt; 标签被添加到 CSS 类为 sr-only 的 DOM。
    • 额外的 JavaScript 被写入 DOM,其中:
      1. 找到所说的&lt;meta&gt;元素。
      2. 检查所述元素是否具有设置为 absolute 的 CSS 属性 position
      3. 如果未设置此类属性值,则会向 DOM 写入一个额外的 &lt;link&gt; 元素,其中 href~/lib/bootstrap/dist/css/bootstrap.min.css

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

    <meta name="x-stylesheet-fallback-test" content="" class="sr-only" />
    

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

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

    不出所料,FallbackTestClass 的值是从&lt;link&gt;asp-fallback-test-class 属性中获得的。

    在这个元素被插入之后,一个对应的&lt;script&gt; 块也被插入(source)。代码是这样开始的:

    // 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("\",");
    

    这里有一些有趣的事情:

    • 注释的最后一行,指的是占位符{0}{1}{2}
    • FallbackJavaScriptResourceName,表示输出到 HTML 中的 JavaScript 资源。
    • FallbackTestPropertyFallbackTestValue,分别从asp-fallback-test-propertyasp-fallback-test-value属性中获取。

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

    function loadFallbackStylesheet(cssTestPropertyName, cssTestPropertyValue, fallbackHrefs, extraAttributes)
    

    结合我之前提到的注释的最后一行以及asp-fallback-test-propertyasp-fallback-test-value 的值,我们可以推断它是这样调用的:

    loadFallbackStylesheet('position', 'absolute', ...)
    

    我不会深入研究 fallbackHrefsextraAttributes 参数,因为它们应该有些明显且易于自己探索。

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

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

    脚本获取相关的&lt;meta&gt; 元素(假定它直接位于&lt;script&gt; 本身的上方)并简单地检查它是否具有设置为absoluteposition 属性。如果没有,则会将额外的 &lt;link&gt; 元素写入每个后备 URL 的输出。

    【讨论】:

    • 我不明白如何验证除 JQuery 和 bootstrap.js 之外的其他脚本,假设我正在使用 Slick-slider,当我检查 Window 时如何检查它是否已加载。光滑它未定义..
    • 我有类似的问题,例如 Offir Pe'er with jquery.unobtrusive-ajax.js..
    【解决方案2】:

    好的,我想我现在明白了,结合@KirkLarkin 的回答和常识。

    sr-only 应用于隐藏的meta 元素。如果加载了引导程序,则该元素将获得position:absolute 的 css 值。这样就测试过了,如果是,那么说明Bootstrap已经加载完毕。

    因此,对于任何库,您需要选择一个只有该库才能执行的好示例,并相应地设置隐藏的 &lt;meta&gt; 标记的样式,然后指定要测试的 css 样式以及您期望的值。

    对于 javscript,它更容易,因为您可以只测试库本身,它通常会在 window 或 DOM 中添加一些众所周知的变量。所以对于 jQuery,它是 window.jQuery,对于 Bootstrap,它可以被测试为 window.jQuery &amp;&amp; window.jQuery.fn &amp;&amp; window.jQuery.fn.modal 等等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-05
      • 2019-11-02
      • 2017-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多