在 Chrome 内容脚本中使用模板的建议方法是什么?

sat*_*oru 6 javascript google-chrome google-chrome-extension

我在 Chrome 内容脚本中使用了几个模板来elements添加到匹配的页面。

目前我将这些模板存储string在脚本中,但我想知道是否有更好的方法来做到这一点。

jjp*_*aga 5

tl;dr 回答- 是的,您可以将它们存储在<script type="text/html">标签中或通过 ajax 动态加载它们。示例在这里(来自 KnockoutJS)和这里。将它们存储在具有正确扩展名的文件中,并使用带有 id X 的空标签,然后$("#X").load("/path/to/template", function() { renderX(); })

长答案和深刻的想法,继续阅读......

请确保系统的模板/视图或相关 GUI 组件位于单独的文件中(继续阅读以了解原因)

作为一名前端工程师,我学会了尽可能保持各层分离;这可以帮助您的团队更好地理解您的代码并使其更易于维护。将模块中的各层分开,然后通过“组装”机制组装它们可能是软件工程中的最佳实践之一。这种做法的一些好处包括:

  • 可维护性:多个开发人员可以浏览和编辑代码的单个部分,以创建更强大的软件。
  • 可读性:随着语言数量的增加,你不能指望每个人都能理解这些 X 或 Y 语言的所有语法;在单个文件中混合语言只是让代码审阅者感到困惑并让他花费更多时间的第一步。
  • 可访问性:例如,html、jade、haml、smarty、twig、erb 或其他模板文件。这些文件应始终以正确的扩展名命名,以帮助代码编辑器和 IDE 进行语法突出显示。开发人员只需浏览一个文件夹即可知道这些文件的用途。脚本或机器人可以仅从扩展中得出重要信息。

通过将视图保存在单独的文件中,其他编码人员可以查看它们并了解系统的重要层,而无需了解整个应用程序;当开发人员只需要查看这些具体文件时,甚至协作也会变得更加容易。通过bashing或脚本编写,即使是具有数千个“视图”(如文件)的大型体系结构系统也可以被过滤,以便仅输出需要审查的内容。

(现在我希望我说服你从代码中删除你的字符串并创建一个新文件并在那里,否则我真的需要提高我的写作技巧)

那么,当我们将模板移动到外部文件后,下一步该做什么呢?

关于 Javascript 和 Chrome 扩展的一句话

Javascript 没有默认的模板功能(哎呀,它甚至没有模块化功能,尽管一些聪明的人正在为 ECMAScript Ed. 6 开发它,耶!),这意味着我们需要使用模板图书馆为此。假设您正在使用 Mustache、Underscore 类似的模板,因此使用它的库来渲染它。

大多数模板引擎都使用臭名昭著的eval,这可能会给您的代码带来漏洞,而 Chrome 扩展程序非常不喜欢这种漏洞。Chrome 扩展开发团队甚至强制执行了该manifest.json文件的新版本以禁止eval,并让开发人员可以选择使用沙盒页面来执行此操作。对我们来说幸运的是,他们决定稍微放松一下政策,我们可以继续在我们manifest.json.

这意味着我们需要解决两个问题,而不是一个问题:“加载模板”和“以某种方式渲染模板,不会吓坏新的 CSP 版本,以防 Chrome 扩展开发团队改变他们的策略”。头脑”。

加载模板

幸运的是,加载模板可以通过 AJAX 通过 XML HTTP 请求来完成。只需将 url 指向文件名,您就可以收到字符串形式的模板,这可能是您最初的设置。这是我用 KnokcoutJS 做的一个例子:

 $("#aiesecTemplate").load('js/libs/aiesec/aiesecTemplate.html', function() {
      ko.applyBindings(AIESECViewModel);
 });
Run Code Online (Sandbox Code Playgroud)

浏览器不会将其呈现为 DOM 的一部分#aiesecTemplate<script type="text/html">您可以将其与其他模板机制一起使用,以便实际组装 DOM。如果您已经对此有了解决方案,那么这可能就是答案的结束,您可以继续您的生活。如果您想知道我们如何从那里渲染代码,请继续阅读。

渲染模板

Chrome 开发团队建议我们对渲染过程进行沙箱处理,因为大多数模板引擎库都不符合 CSP 标准(AngularJS是一个例外)。这是沙盒页面的代码摘录。

iframe.contentWindow.postMessage(message, '*');
Run Code Online (Sandbox Code Playgroud)

iframe其中沙盒页面中的特定 DOM Iframe 元素以及src具有模板引擎的页面的属性在哪里;message之前已加载字符串模板,因此在发布消息后, iframe 内的window.addEventListenerformessage可以毫无问题地渲染它。有关沙盒评估的更多信息可以在此处阅读

结论

如果你能到达这里,那就太棒了!我的回答可能不会那么无聊。最后一点,您可能会想“AMD 或 RequireJS 怎么样?”;老实说我还没有尝试过,但真正聪明的人认为 AMD 不是最好的方法。通过 XML HTTP 请求加载可能不会更好,但如果您认为它会影响您的性能(我在我的应用程序中使用了它,但它没有),您始终可以使用一些事件页面Web Workers