【问题标题】:How to get access to request object from custom handlebars helper如何从自定义车把助手访问请求对象
【发布时间】:2019-07-09 03:06:49
【问题描述】:

我正在使用带有 node.js 和 express 的车把,并且我有一个自定义注册的温度显示助手,我想从页面 URL 访问查询参数。

帮助程序背后的概念是根据?tempFormat=FtempFormat=C 是否在URL 中自动处理华氏到摄氏度的转换。这是我想要的自定义助手的伪代码:

hbs.registerHelper("formatTemp", function(temp) {
    if (query parameter says to use Fahrenheit) {
        temp = toFahrenheitStr(temp);
    }
    return temp;
});

所以,我希望我的模板看起来像这样:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

我现在正在通过拉取request.query.tempFormat 并将其放入提供给模板渲染的数据中来解决这个问题:

app.get('/debug', function(request, response) {
    var tempData = {
        temperatures: data.temperatures,
        units: request.query.tempFormat || "C"
    };
    response.render('debug', tempData);
});

然后,在模板中传递该数据:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp ../units}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp ../units}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

但是,这似乎很麻烦,因为我必须将温度单位传递给每个模板渲染调用,然后我必须将它们放在我希望它们被温度显示使用的每个模板中。他们已经坐在请求对象中了。所以,我想弄清楚如何从把手自定义帮助函数访问请求对象?这样,我可以为每个渲染保存代码并在每个模板中保存代码,并让 tempFormat 查询参数自动应用于我的模板中 formatTemp 的任何使用。

有谁知道如何在不使用全局的情况下从把手自定义助手访问请求对象?

【问题讨论】:

  • 在相关说明中,有人知道是否有一个讨论车把问题的论坛,在那里它可能更有可能找到车把专家(因为没有关于这个问题的活动)?跨度>
  • location.pathname.indexOf('tempFormat=F')
  • @raidendev - 这不是浏览器,它是运行 node.js 的服务器,如果它是浏览器并且我正在尝试,它会在 location.search,而不是 location.pathname避免使用全局变量,这样多个请求就不会出现问题。

标签: javascript mustache handlebars.js


【解决方案1】:

首先,您需要通过在路由之前的任何位置注册中间件,将您的请求对象分配给本地响应

app.use(function(req,res,next){
    res.local.req = req;
    next();
})

然后你可以在你的助手中访问查询对象

<div class="atticTemp">{{formatTemp atticTemp ../req.query.tempFormat }}</div>

【讨论】:

  • 可能是特定于版本的,但我必须使用:{ res.locals.req = req; }
【解决方案2】:

Handlebars 总是使用当前上下文调用助手 this,因此您可以使用 this 调用块来评估当前上下文中的块。

https://handlebarsjs.com/block_helpers.html#basic-blocks

您可以将@Roland 的答案与此功能结合起来,让您的助手使用单个参数确定正确的格式。

首先添加一个中间件,将请求中的值注入到车把的上下文中。

app.use(function(req, res, next){
    var tempUnits = this.req.query.tempFormat || 'C';
    this.locals.tempUnits = tempUnits;
    next();
})

然后在你的中间件函数中,你可以使用this.tempUnits来访问你注入的值。

hbs.registerHelper("formatTemp", function(temp) {
    var units = this.tempUnits;
    if (units == 'F') {
        temp = toFahrenheitStr(temp);
    }
    return temp;
});

然后你可以让你的单参数助手从请求中获取数据。

<div class="atticTemp">{{formatTemp atticTemp}}</div>

注意:您可以添加整个请求对象,但让中间件注入您想要的值会更简洁。

【讨论】:

  • 这仅适用于顶级 hbs 代码。当您处于不同的环境中时,例如#each 块,上下文切换,this 变量代表当前迭代项。在这些情况下,res.locals 在帮助程序中不可用。
【解决方案3】:

我正在使用 express-handlebars 包。您可以在其配置对象上注册助手,如下所示。与您的方式略有不同,但您会明白的。为了缩短事情的时间,我刚刚在您的辅助函数中添加了第二个参数(:

var exphbs  = require('express-handlebars');

app.engine('handlebars', exphbs({
    defaultLayout: 'layout',
    helpers : {
        formatTemp: function(temp, unit) {
            console.log(unit);
            if (unit=="F") {
                return temp;
            } else {
                return 32 + (temp* 9 / 5);
            }
        }
    }

上下文数据结构和用法是一样的。

经过测试。

【讨论】:

  • 对不起,但这没有帮助。我已经注册了一个助手(它显示在我的问题中)。而且,单位需要来自 cookie 或查询参数,而不是来自模板。
  • 您只需要在已经注册的辅助函数中添加第二个参数(单位)。价值的来源不是这里的问题。无论您从哪里获得单位 (C|F) 值,您所要做的就是将此值传递给视图数据上下文(作为 res.render 函数的第二个参数),然后在您的帮助程序调用中使用它。
  • iow,您离解决方案仅一步之遥。如果您将助手调用更改为 {{formatTemp outsideTemp ../units}},那么您的助手应该收到 2 个参数......就是这样。
  • 试试这个:hbs.registerHelper("formatTemp", function(temp, unit) { if (unit === "F") { temp = toFahrenheitStr(temp); } return temp; });
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多