【问题标题】:Angularjs directive, different ways of doing template to avoid {{}} resolution problemsAngularjs 指令,做模板的不同方式来避免 {{}} 解析问题
【发布时间】:2019-02-13 08:24:48
【问题描述】:

我们有一个 Angular 应用程序,最近我们添加了一种机制,允许用户选择性地上传自定义字体,然后以该自定义字体呈现应用程序。实现它的人投入了一个指令,该指令声明一个块并根据用户在页面上的自定义定义字体覆盖。

对 QA 团队进行调整的是,在自定义数据返回之前,他们会看到 /{{fontPath}}/{{customFont}} 的 404 请求,直到所有摘要周期都完成。

我一直试图让 404 消失,但遇到了一些让我困惑的事情。

首先,这就是事情的样子

<div font-override ng-if="customFont"></div>

指令 templateUrl 看起来像

<style>
    @font-face {
        font-family: 'FontOverride';
        src: url("{{fontPath}}{{customFont}}") format('woff');
        font-weight: normal;
        font-style: normal;
    }

    @font-face {
        font-family: 'FontOverride';
        src: url("{{fontPath}}{{customFont_bold}}") format('woff');
        font-weight: bold;
        font-style: normal;
    }

    @font-face {
        font-family: 'FontOverride';
        src: url("{{fontPath}}{{customFont_italic}}") format('woff');
        font-weight: normal;
        font-style: italic;
    }

    @font-face {
        font-family: 'FontOverride';
        src: url("{{fontPath}}{{customFont_boldItalic}}") format('woff');
        font-weight: bold;
        font-style: italic;
    }

    .ourApp *:not(.fa) {
        font-family: 'FontOverride' !important;
    }
</style>

当 templateUrl 内容被换入时,会立即出现对 "/{{fontPath}}{{customFont}}" 的 404 请求

我一直在玩一堆东西,试图让它消失。我将 ng-cloak 放在 div 和 templateUrl 内容中。它没有用。

我尝试定义 ng-cloak 样式并将其设置为样式节点上的 css 类(在另一篇文章的堆栈中找到)但它不起作用。

在野兔上,我尝试获取 templateUrl 文件的内容并将其嵌入到带有模板文字的指令代码中

template: ``

起初这不起作用,但在我删除 url("{{fontPath}}{{customFont}}") 周围的引号后开始。

不清楚模板为什么或如何或在什么时候得到解决,或者为什么它比 templateUrl 更好(wrt 404)。我的意思是,根据我对 ECMA6 的发现,实际的模板位是 ${},而不是 {{}}。

然后我在 IE11 中尝试了它(因为我们名义上仍然支持它),当然模板文字在那里不起作用。所以我尝试将多行的东西构建为旧字符串

"<style>\r\n" +
"    @font-face { font-family: 'FontOverride'; src: url('{{fontPath}}{{customFont}}') format('woff'); font-weight: normal; font-style: normal; } \r\n\r\n" +
...
"    .ourApp *: not(.fa) {\r\n         font-family: 'FontOverride' !important;\r\n }\r\n</style>\r\n"

样式的最后一行似乎对换行符/空白更敏感,所以我试图保留它。

这在我尝试过的任何浏览器中都有效。当我检查元素时,Chrome、IE、Edge 都以相同的方式呈现它,但在任何阶段都没有获取或应用字体。 Firefox 似乎首先从文字中去除了换行符。

所以... 1) 为什么 template: `` 一开始就没有产生 404 请求就可以工作?

2) 我试图使用 ECMA6 模板文字来获取多行常量;我没想到模板结构可以直接工作,因为 ECMA6 使用 ${} 而不是 {{}},但也许 EMCA6 模板文字也有角度语法?或者也许 angular 正在插入 jquery 语法并成为同义词?

3) 为什么带有 \r\n 的笨重旧字符串文字在大多数浏览器中呈现相同但不会产生功能影响? Kinda 回到了 ECMA6 模板文字以不同方式通过 Angular 评估的理论。

感谢您的见解。

谢谢。

【问题讨论】:

    标签: javascript css angularjs


    【解决方案1】:

    在 Angular 在页面中实例化之前,浏览器将解析任何 &lt;style&gt; 标签(并且将加载 src 的标签)。这意味着在应用 ng-if 之前。

    您需要存储该标记,而不允许浏览器将其解析为&lt;style&gt; 标记。

    这种情况的典型解决方案是将其包装在一个

    <script type="text/template">
      <style>...</style>
    </script>
    

    这是动态模板的常见模式。加载组件后,按 id 选择脚本,获取其.html()$compile 并追加。

    由于某种原因,我无法让它在 [SO] 上运行,但您可以在这个小提琴中看到它:https://jsfiddle.net/websiter/khjr70ep/

    我没有你的文件,所以我使用了一些随机的谷歌字体,但你可以看到它在解析之前没有加载。

    它会应用字体。

    【讨论】:

    • 感谢您的回复。
    • 请求在ng-if 被应用之前离开的事实告诉我们浏览器在 Angular 编译它之前看到了该标记。试试我的建议。它应该工作。我将尝试添加一个通用示例。如果你有 minimal reproducible example 我可以使用它,特别是如果它有问题。
    • @user,添加了一个小提琴。我不知道为什么Stack Overflow 在此处尝试相同的 sn-p 时会阻止它,但您可以看到它在小提琴中正常运行。
    • 我最终做了类似的事情。我将模板设为空,在指令链接中设置一个监视以填充模板并在设置时 $compile。仍然不确定为什么模板文字在没有 $compile 或其他问题的情况下可以工作,但解决它仍然很好。
    【解决方案2】:

    一种方法是在模板中声明一个带有 id 属性的空样式标签,例如:

    <style id="app-custom-font-css"></style>
    

    然后,当字体已经上传到其最终位置并且您获得了数据时,使用它来构建 CSS 内容:

    // Update <style> tag with specific ID
    const styleTag = document.getElementById('app-custom-font-css');
    styleTag.innerHTML = myCustomCssContentString;
    

    以上可以通过指令或在您的应用加载时完成。希望对您有所帮助。

    【讨论】:

    • 感谢您的回复。我可能最终会沿着这样的路线走下去,但我想先了解一些关于 Angular 消化道的事情——比如为什么模板文字在通过 templateUrl 拉入时不会产生 404 请求而工作会打开一个产生404. 为什么多行常量(不是模板文字)即使呈现相同(在大多数浏览器中)也不会产生函数结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多