【问题标题】:Node js - Compile handlebars view without rendering itNode js - 编译车把视图而不渲染它
【发布时间】:2018-11-13 01:41:39
【问题描述】:

我的问题很简单:我想编译一个 Handlebars 视图然后不渲染它——相反我想使用编译后的 HTML 服务器端。在研究这个问题时,this 是我能找到的最接近我的问题的,但除非我有误解,否则他们在这个问题上所做的一切都是在服务器端创建一个 HTML 字符串并用数据填充它。这是不够的,因为我不想创建任何 HTML 字符串,我真的想像往常一样将我的 HTML 存储在 .hbs 文件中,然后编译一个视图(即发送我的变量),而不是显示它一个用户(无论如何都不可能,因为它只是一个 API 服务器),我想让编译后的 HTML 将其发送到 Mailgun(但我想将它发送到 Mailgun 的事实超出了范围,答案应该最好只告诉我如何编译视图并能够(例如)console.log() HTML)。

我正在使用 Node v9.8.0

包:

  • 正文解析器:1.18.3
  • cors:2.8.4,
  • dotenv:5.0.1,
  • 快递:4.16.3,
  • hbs:4.0.1
  • 时刻:2.22.1

如果我需要提供任何其他信息,请告诉我,我没有包含任何我尝试过的示例代码的原因是我根本不知道该尝试什么。我所尝试的只是在我的路线中使用let emailHtml = res.render('email/contactReceipt.hbs', { name:req.body.name }),但这给了我错误Cannot set headers after they are sent to the client

旁注:我对 Node.js 还很陌生,它不是我正常堆栈的一部分。我注意到其他人使用包'express-handlebars'甚至只是'handlebars',所以如果我使用的('hbs')实际上与Handlebars没有任何关系,或者如果我不能完成我正在尝试做的事情,让我知道。

【问题讨论】:

    标签: javascript html node.js handlebars.js


    【解决方案1】:

    res.render 接受第三个参数,这是一个包含渲染字符串的回调,不发送响应,从而避免了Headers already sent 错误

    res.render(view [, locals] [, callback])
    

    渲染一个视图并将渲染后的 HTML 字符串发送给客户端。 可选参数:

    • locals,一个对象,其属性为 看法。
    • callback,一个回调函数。如果提供,该方法返回 可能的错误和呈现的字符串,但不执行 自动响应。发生错误时,该方法调用 next(err) 内部。
    res.render('email/contactReceipt.hbs', { name:req.body.name }, (err, html) => {
        if(err) 
           return console.error(err);
        // do whatever you want here with `html`
    });
    

    您也可以使用app.render,它类似于res.render,但适用于全局级别,并且始终采用第三个参数。

    app.render('email/contactReceipt.hbs', { name:req.body.name }, (err, html) => {
        if(err) 
           return console.error(err);
        // do whatever you want here with `html`
    });
    

    或者你可以直接编译模板,以后做任何你想做的事情。

    const hbs = require('hbs');
    
    const template = hbs.compile('<h1>{{title}}</h1>');
    
    const html = template({ title: 'Handlebars' });
    console.log(html); // <h1>Handlebars</h1>
    

    如果您想从磁盘读取模板内容,只需使用fs.readFile 并将内容传递给hbs.compile

    const hbs = require('hbs');
    const fs = require('fs');
    const readFile = require('util').promisify(fs.readFile);
    
    async render(file, data) {
        const content = await readFile(file, 'utf8');
        // Implement cache if you want
        const template = hbs.compile(content);
    
        return template(data);
    }
    

    【讨论】:

    • 好吧,很酷,但问题出在这里,我可能应该在我的问题中包含这个,你有hbs.compile() 我想给它我的views 目录中的文件路径,例如hbs.comple('email/contact.hbs')。能做到吗?
    • 只需使用fs 读取文件内容,并将其传递给车把,这就是res.render 所做的。
    • 你是老板。我按照您解释的方式设置了res.render(),并且成功了。我也尝试了readFile 的方式,但我不确定在我的路线中将async 的东西放在哪里?在我的路线之外,就像一个函数?不确定..无论如何,谢谢您的帮助,我想我可以从这里拿走。
    • 还添加了app.render 功能。并且render函数应该放在你的路由之外,然后让你的路由回调,一个async,这样你就可以在里面使用await。这不是强制性的,因为您可以调用render.then(),但使用await 要简单得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    相关资源
    最近更新 更多