如何在 Handlebars 模板中调用工厂函数的 getter 方法?

问题描述 投票:0回答:1

我有一个工厂函数,如果这不是标准行话,我指的是一个返回对象的函数。这个工厂函数称为

Person
。我现在要说的是 - 我不想听到“使用构造函数”。工厂功能更好。

我还有一个对象数组,

allPeople
是使用这个工厂函数制作的。

如果从我对“工厂函数”的使用中不清楚,这些对象实际上是包含 getter 方法的对象,在本例中是

getPerson
,以及其他函数(生成的对象通过闭包作用域来区分)。要获取实际数据,必须对
getPerson()
对象(由
Person
函数生成的对象)调用
Person

我想我应该解释一下,这样我们就处于同一基础上。

我正在尝试使用 Handlebars 为

Person
中的每个
allPeople
对象插入一个元素。对于每个
Person
,一个
<p>
元素将显示
name
值,另一个
<p>
元素将显示
age
值。

下面我包含了js文件和html文件。

script.js

//Factory Function
const Person = (givenName, givenAge) => {
    theName = givenName;
    age = givenAge;
    const getPerson = () => {
        const obj = { theName, age };
        return { theName, age };
    }
    return {getPerson};
}
//DOM Element Access
const templateElement = document.getElementById('templateHB');
const templateDestination = document.getElementById('destination');
//Context
allPeople = [
    Person('Jim', 32),
    Person('Lily', 46)
];
const context = {
    people: allPeople
};
//Templating
const template = Handlebars.compile(templateElement.innerHTML);
const compiledHTML = template(context);
templateDestination.innerHTML = compiledHTML;

index.html

<!DOCTYPE html>
<html lan="en">
<head>
    <meta charset"UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>For SO use</title>
    <script src="./script.js" defer></script>
    <script src="./handlebars.js"></script>
    <script id="templateHB" type="text/x-handlebars-template" defer>
        {{#each people}}
        <p>{{this.getPerson().theName}}</p>
        <p>{{this.getPerson().age}}</p>
        {{/each}}
    </script>
</head>
<body>
    <div id="destination">

    </div>
</body>
</html>

当我在浏览器中打开index.html(我尝试过Google Chrome和Firefox)时,会发生以下错误:

.....

<p>{{this.getPerson().theName}
^ 期待“ID”,结果“无效”

如何正确实现这个设计?

javascript html handlebars.js
1个回答
0
投票

我从您的帖子中了解到您并不是在寻找反对使用此“工厂功能”的建议。然而,我觉得如果我没有声明我没有看到这段代码的价值,我的帖子就不完整,而且我认为这会让事情变得不必要的复杂。

但是继续“工厂功能”。

有问题。事实上,您没有在每个赋值

var
const
之前放置
let
theName = givenName
age = givenAge
意味着
theName
age
是全局范围的,因此对
getPerson()
的任何调用将返回提供给最后一次调用
theName
的参数的
age
Person()

一旦解决了这个问题,我建议让您的模板幸福地不知道“工厂功能”。您可以通过将

allPeople
数组映射到每个人都能理解的普通对象来做到这一点:

const allPeople = [
  Person('Jim', 32),
  Person('Lily', 46)
].map(person => person.getPerson());

您的(简化的)模板将变为:

{{#each people}}
  <p>{{theName}}</p>
  <p>{{age}}</p>
{{/each}}

这里是一个工作示例的小提琴。

如果出于某种原因,您确实希望模板处理

getPerson
方法,那么我认为您将需要一个自定义 Handlebars 助手:

Handlebars.registerHelper('getPersonProperty', function (person, property) {
  return person.getPerson()[property];
});

在模板中使用此助手将如下所示:

{{#each people}}
  <p>{{getPersonProperty this 'theName'}}</p>
  <p>{{getPersonProperty this 'age'}}</p>
{{/each}}

并且这里是一个关于这个例子的小提琴。

© www.soinside.com 2019 - 2024. All rights reserved.