【问题标题】:How to see all available variables in handlebars template如何查看车把模板中的所有可用变量
【发布时间】:2013-11-17 00:17:58
【问题描述】:

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

有一个相关的问题,但您必须知道使用它的范围内的变量: How do I add console.log() JavaScript logic inside of a Handlebars template?

如何输出所有变量?

【问题讨论】:

标签: javascript debugging ember.js handlebars.js


【解决方案1】:

您可以通过利用输入模板字符串的Handlebars.parseWithoutProcessing 来做到这一点。如果您使用 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 向用户询问他们的姓名和奖金金额。该示例还实现了一个助手formatCurrency。你可以在这里看到它:https://codepen.io/tinacious/pen/GRqYWJE

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      一个不错的选择是使用 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('.'));
          }
      });
      

      【讨论】:

      • Must pass iterator to each
      • 这个答案中的选项 1 对我很有帮助,尽管不如他们的选项 2 或选项 3 完整。:)
      • 日志对我有帮助。 tnx
      【解决方案4】:

      确保您试用 Firebug - 您会对事物有不同的看法,我发现这很有帮助。但不要完全放弃 chrome;在某些时候你会需要Ember Inspector

      我使用的是same debugging helper everyone recommends,这就是 Chrome 的显示方式:

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

      【讨论】:

      • Firebug / Chrome Inspector 显示相同的数据,只是格式不同。而且,正如@doub1ejack 提到的,Chrome Inspector 有一个很棒的(很棒的)扩展。我认为有关 Firebug 的 cmets 与该帖子无关。感谢您对调试助手的帮助。
      • 不同的格式可以产生巨大的影响,尤其是当您处于不熟悉的环境中时。由于这些屏幕截图所示的原因,我发现萤火虫(最初)提供更多信息。不过我完全同意,Ember Chrome 扩展非常棒——它只是在 OP 的情况下对我没有帮助。
      • 很好的编辑。这篇文章现在的偏见要小得多了 :) 你说服我再次尝试 Firebug,谢谢。
      • Ember Inspector 现在可作为 Firefox 插件使用:Ember Inspector for Firefox
      【解决方案5】:

      您提到的示例 Ember 应用程序在 its app.js 中定义了其 EmberObjects。所以基本上,对象上可用的是在那里定义的属性。 (例如 subreddit 有一个 title 等)。

      如果您想要一种全局可用的方法将对象的属性模式转储到控制台,一种方法是创建一个“调试”帮助程序,该帮助程序遍历传入上下文的成员并将它们写出。比如:

      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);
              }
          }
      });
      

      然后在任何你想检查的地方调用它:

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

      这将使用范围内的任何 EmberObject,因此如果要检查列表元素而不是具有该列表的对象,请将其弹出到 {{#each}} 中。

      【讨论】:

      • 我喜欢这种方法。 {{debug .}} 的周期是多少?我已经尝试过了,到目前为止我还没有看到任何有用的变量显示。我似乎每次都看到相同的 5 个字符串:viewbufferisRenderDatakeywordsinsideGroup。我已经在我的模型中添加了一个属性,并且希望至少能看到这一点..
      • . 表示当前上下文对象 - 它类似于 this 用于您的上下文。您可以使用.. 来“出”一级(不是向上!),并获取包装器的上下文。
      • 这看起来虽然您在模板中获得了options.data,而不是context - 这些都是Ember 属性。您是否可能在不传入对象的情况下调用模板?
      • 看看view.js,来自Ember 的1183 行:github.com/emberjs/ember.js/blob/… render 函数将获取您的模板并将其传递给context,该数据对象为options.data.
      • 嗯..我不知道。我没有明确地将任何对象传递给模板(我不这么认为)——我认为 Ember 是为我做的。对于这个示例 (github.com/eviltrout/emberreddit/blob/master/js/app.js),您会建议哪些更改?
      【解决方案6】:

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

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

      1. 预编译一个模板(见command line source,我觉得函数叫handlebars.precompile()
      2. 探索 AST

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

        • 这听起来不错(希望能够使用检查器)。我不知道在哪里设置断点。我正在探索来自github.com/eviltrout/emberreddit 的示例项目。它没有明确的视图(我假设这是渲染模板的地方),我不能在模板本身中放置断点。我应该去哪里看?
        • @doub1ejack 使用 Handlebars 调试器助手在模板内设置断点,例如 {{debugger}},然后在 Chrome 开发工具的 Sources 选项卡中检查 Local Scope Variables。
        • @EliseChant 哇,我不知道你能做到 {{debugger}},很高兴知道。
        猜你喜欢
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 2013-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-05
        相关资源
        最近更新 更多