22

我正在开发我的第一个 Ember.js 应用程序,但在连接所有点时遇到了一些麻烦。如果我可以在给定的车把模板中看到所有可用的变量,那将非常有帮助。

有一个相关的问题,但您必须知道使用它的范围内的变量: 如何在 Handlebars 模板中添加 console.log() JavaScript 逻辑?

如何输出所有变量?

4

7 回答 7

12

一个不错的选择是使用 Handlebars 助手在模板中调试“this”的值:1。

{{#each}}
    {{log this}}    
{{/each}}

或者,2.类似于@watson 建议

{{#each}}
    {{debugger}}
{{/each}}

然后在开发工具中深入了解“this”的本地范围变量

在此处输入图像描述

或者,3. 您可以直接从 Controller init 方法中记录内容,例如:

App.UsersController = Ember.ArrayController.extend({
    init: function() {
        console.log(this);
        console.log(this.getProperties('.'));
    }
});
于 2014-06-23T10:30:35.557 回答
6

确保你尝试了 Firebug——你会对事物有不同的看法,我觉得这很有帮助。但不要完全放弃 chrome;在某些时候你会需要Ember Inspector

我正在使用每个人都推荐的调试助手,这就是 Chrome 显示它的方式:

Chrome 检查器不是很有帮助

当我在 firebug 中展开同一个对象时,我得到以下信息,包括我正在寻找的变量 (sources[]) 以及我在 Chrome 中没有看到的其他一些有用的属性。

Firefox 有更多可供我使用

于 2013-11-06T16:38:24.193 回答
5

几年前我创建了Barhandles 。它将使用 Handlebars 解析器生成 AST,然后从中提取变量引用。该extractSchema方法将 - 很好 - 提取模式。该架构不是基于 JSON Schema 或 Joi 或任何东西。这是一种本土格式,可以捕获您可能从 Handlebars 模板中提取的大部分内容。

所以,这barhandlers.extractSchema('{{foo.bar}}')会产生:

{
  "foo": {
    "_type": "object",
    "_optional": false,
    "bar": {
      "_type": "any",
      "_optional": false
    }
  }
}  

它将考虑到 an{{#if expr}}将自动使嵌套引用成为可选。它可以根据{{#with expr}}构造正确处理范围更改,并且还允许您添加对自己的自定义指令的支持。

我们用它来验证我们传递给模板的数据结构,它为此目的工作得很好。

于 2019-07-03T18:35:07.003 回答
2

如果您确实需要转储模板中的变量,您可以探索模板 AST 并输出相关节点的内容(请参阅编译器源代码)。这不是一件容易的事,因为您必须通过试验和错误找到自己的方法,而且代码非常低级,没有那么多注释。

似乎 Handlerbars 没有您所要求的快捷方式,因此步骤如下:

  1. 预编译一个模板(见命令行源码,我认为该函数被调用handlebars.precompile()
  2. 探索 AST
于 2013-11-05T23:28:56.157 回答
1

The sample Ember app you mention defines its EmberObjects right in its app.js. So basically, what's available on the objects are the properties that are defined onto them there. (e.g. subreddit has a title, etc).

If you want a globally available way to dump an object's property schema out to the console, one approach would be to create a "debug" helper that walks the members of the passed-in contexts and writes them out. Something like:

Handlebars.registerHelper('debug', function (emberObject) {
    if (emberObject && emberObject.contexts) {
        var out = '';

        for (var context in emberObject.contexts) {
            for (var prop in context) {
                out += prop + ": " + context[prop] + "\n"
            }
        }

        if (console && console.log) {
            console.log("Debug\n----------------\n" + out);
        }
    }
});

Then call it on whatever you want to inspect:

<div>Some markup</div>{{debug}}<div>Blah</div>

This will use whatever EmberObject is in scope, so pop it inside of an {{#each}} if you want to inspect the list elements, as opposed to the object with that list.

于 2013-11-07T16:31:06.270 回答
1

您可以通过利用Handlebars.parseWithoutProcessingwhich 接受输入模板字符串来做到这一点。如果您使用 TypeScript,则返回特定类型hbs.AST.Program。您可以仅过滤 mustache 语句,然后遍历这些语句以获取变量名称。

此方法还支持 Handlebars 助手,因此您可以获得密钥,但正因为如此,此函数有点复杂,因为您需要检查 mustache 语句上的不同属性:

/**
 * Getting the variables from the Handlebars template.
 * Supports helpers too.
 * @param input
 */
const getHandlebarsVariables = (input = '') => {
  const ast = Handlebars.parseWithoutProcessing(input);
  return ast.body
    .filter(({ type }) => type === 'MustacheStatement')
    .map((statement) => statement.params[0]?.original || statement.path?.original);
};

这是 TypeScript 版本,由于条件属性,它有点涉及,但可以帮助解释更多类型:

/**
 * Getting the variables from the Handlebars template.
 * Supports helpers too.
 * @param input
 */
const getHandlebarsVariables = (input: string): string[] => {
  const ast: hbs.AST.Program = Handlebars.parseWithoutProcessing(input);

  return ast.body.filter(({ type }: hbs.AST.Statement) => (
    type === 'MustacheStatement'
  ))
  .map((statement: hbs.AST.Statement) => {
    const moustacheStatement: hbs.AST.MustacheStatement = statement as hbs.AST.MustacheStatement;
    const paramsExpressionList = moustacheStatement.params as hbs.AST.PathExpression[];
    const pathExpression = moustacheStatement.path as hbs.AST.PathExpression;

    return paramsExpressionList[0]?.original || pathExpression.original;
  });
};

我制作了一个 Codepen 来说明这一点。本质上,给定以下模板:

Hello, {{first_name}}! The lottery prize is {{formatCurrency prize_amount}}! Good luck!

它将window.prompt用于询问用户的姓名和奖金金额。该示例还实现了一个 helper formatCurrency。你可以在这里看到它:https ://codepen.io/tinacious/pen/GRqYWJE

在此处输入图像描述

于 2020-11-09T06:29:10.277 回答
0

模板中可用的变量仅受您用于呈现模板的模型的约束。

您应该在您的应用程序中设置一个断点来渲染模板并查看此时您的模型中的内容,这将您可以放入模板中的内容。

于 2013-11-05T22:56:16.670 回答