使用模块导出将模板文字与逻辑分开

Jen*_*ell 9 html javascript templates literals module.exports

我正在试验 HTML 字符串模板文字(使用 NodeJS 的电子)。

它运作良好,但看起来一团糟。我想念的是 HTML 和逻辑之间的分离。

这是我所拥有的

module.exports = {
  snippet: (value1, value2) => {
    return `
<div>
  <h1>Hello ${value1 + ' - ' + value2}</h1>
</div>
`;
  },
};
Run Code Online (Sandbox Code Playgroud)

建议输出

我希望我能做的是如下(这不起作用):

module.exports = {
  snippet: (value1, value2) => {
    return require('snippet.html')(value1, value2);
  },
};
Run Code Online (Sandbox Code Playgroud)
<div>
  <h1>Hello ${value1 + ' - ' + value2}</h1>
</div>
Run Code Online (Sandbox Code Playgroud)

为什么它不起作用

字符串是扁平的,不能带参数

我可以从 HTML 文件中以字符串形式获取 HTML。问题是它将是“扁平的”,我不能再使用模板文字中的逻辑了。

eval 邪恶而缓慢

我读过可以将 HTML 作为字符串运行eval以使其再次工作。我还读到它不利于安全并且速度很慢。

其他注意事项

  • 我使用 nodeJS 所以我需要module.exports在 js 文件中使用。
  • 我使用嵌套的片段,所以模板文字仍然可以正常工作很重要。它应该能够接受变量、函数等。
  • 我不介意新的 ES6 语法。
  • 我知道 Vue、React 和其他框架。这次我想保持它很小并且没有设置服务器的麻烦。

更新 - 稍微好一点,但还不够

我现在已经从模板中分离了逻辑。尽管如此,两者都在同一个文件中,这使得 html 的可读性降低。

module.exports = {
  snippet: (value1, value2) => {
    /* Possible to put whatever logic in here */
    return html(value1, value2);
  },
};

function html(value1, value2) {
  return `
<div>
  <h1>Hello ${value1 + ' - ' + value2}</h1>
</div>
`;
}
Run Code Online (Sandbox Code Playgroud)

x00*_*x00 4

  1. 我了解 Vue、React 和其他框架。我想保持它很小,并且这次不需要设置服务器的麻烦。

    开发您自己的模板框架绝不是一件轻松的任务。我不知道你的意思是什么other frameworks,但当你把这个短语与VueReact这样的怪物放在一起时,我猜你不了解小而简单的模板库。我不确定目前的情况,但上次我检查像这个列表中的库或这个列表中的库非常小并且易于使用

  2. 或者也许您会发现这种方法很有吸引力https://jonsuh.com/blog/javascript-templatating-without-a-library/

  3. 您实际上不必module.exports在最新的NodeJS版本上使用

  4. 如果您同意,Update但唯一的问题是模板与代码片段位于同一文件中,那么什么阻止您拆分文件呢?

    // app.js
    console.log(require('./snippet.js').snippet(1,2))
    
    Run Code Online (Sandbox Code Playgroud)
    // snippet.js
    module.exports = {
      snippet: (value1, value2) => {
        /* Possible to put whatever logic in here */
        return require('./template.js')(value1, value2)
      },
    }
    
    Run Code Online (Sandbox Code Playgroud)
    // template.js
    module.exports = (value1, value2) => `
    <div>
      <h1>Hello ${value1 + ' - ' + value2}</h1>
    </div>
    `
    
    Run Code Online (Sandbox Code Playgroud)

作为旁注:

  1. Eval 是邪恶且缓慢的

    来自MDN

    eval()是一个危险的函数,它以调用者的权限执行传递给它的代码。如果您使用可能受到恶意方影响的字符串运行eval(),则您最终可能会使用您的网页/扩展程序的权限在用户的计算机上运行恶意代码。

    因此,如果您只通过它运行自己的代码,eval()则完全可以保存...但是,当然,当您实现模板时,这可能意味着在某些时候您会希望允许用户对模板进行输入,这会带来麻烦。所以,是的,eval对于你的情况来说可能是不安全的。

    我只是想指出这eval是极其危险的,但并不是在所有情况下都是绝对的邪恶。

    而且也不必慢。当你说时,你必须始终问自己:“与什么相比?在什么情况下?”。阅读这篇文章,您就会明白为什么它很慢。但可以并不代表必须

  2. 来自同一段:

    更重要的是,第三方代码可以看到调用 eval() 的范围,这可能会导致类似Function不易受到攻击的攻击。

    您可以考虑使用Function. 这仍然很危险。但情况并非如此。


再考虑一下 - 您应该使用Function,或者干脆放弃完全编写模板引擎的想法。因为它的不安全性并不重要:使用模板文字的想法是不安全的Function

const template = (value1, value2) => `
<div>
  <h1>Hello ${value1 + ' - ' + value2}</h1>
</div>
`
some_node.innerHTML = template("</h1><script>console.log("malicious injection")</script><h1>", "something else")
Run Code Online (Sandbox Code Playgroud)

顺便说一句innerHTML也没有安全感