4

我慢慢开始掌握 EmberJS 的窍门。不幸的是,我遇到了一个我似乎无法解决的问题。

我有一个复杂的数据结构,我通过 JSON 检索它,有多个嵌套数组,我似乎无法嵌套 #each 助手。

我已将模板设置如下(缩短):

{{#each Servers}}
     <div class="server">
          <h1>{{unbound Name}}</h1>
          Time: {{jsonDate CurrentTime}}<br />

          <table>
               {{#each Processes}}
                    <tr>
                         <td>{{unbound Name}}</td>
                         <td>{{unbound Location}}</td>
                    </tr>     
               {{/each}}
          </table>
     </div>
{{#/each}}

第二个循环似乎没有运行,当我修改 Ember 以记录一条消息时,#the second each 被调用,但它似乎不知道该怎么做。

当我用#Queue 替换第二个#each 时,它可以工作,但是在-element 之前,会为列表中的每个元素插入一个“未定义”-text(减1)。

当我将#each 移出另一个循环并放入队列的直接路径(例如Servers.0.Queue)时,它工作正常,所以它肯定不是数据。

我该如何解决?如果嵌套#each 是不可能的,我该如何为其他方法添加“未定义”文本?还有其他可能吗?

PS。出于性能原因,我使用 unbound,我一次更新了 Servers 对象并观察到这一点,因此不需要使用绑定属性 - 因为我注意到它显着降低了浏览器性能(13% CPU 使用率,而 unbound 给了我 0 %)。不确定是否相关。

编辑

请参阅:http: //jsfiddle.net/PTC9B/7/

ServerOverview2a 方法毕竟有效,显然 ServerOverview2b 生成我之前描述的“未定义”文本 - 可能应该为此提交错误报告?

我现在的问题是:为什么嵌套的#each 不起作用而#Processes 起作用?

4

3 回答 3

6

看起来您的哈希中的属性导致了麻烦:使用大写属性Processes不起作用 - 如果您将其更改为processes帮助程序each按预期工作,请参阅http://jsfiddle.net/pangratz666/ndkWt/

<script type="text/x-handlebars" data-template-name="app-server">
    <h1>Default</h1>
    {{#each data.Servers}}
        <div class="server">
            <h1>{{unbound this.Name}}</h1>

            Time: {{unbound this.CurrentTime}}<br />

            <table>
                {{#each this.processes}}
                    <tr>
                        <td>{{unbound Name}}</td>
                        <td>{{unbound Location}}</td>
                    </tr>     
                {{/each}}
            </table>
        </div>
    {{/each}}
</script>​
App = Ember.Application.create({
    ready: function() {
        Ember.View.create({
            templateName: 'app-server',
            dataBinding: 'App.dataController.data'
        }).append();

        App.dataController.getServers();
    }
});

App.dataController = Ember.Object.create({
    data: {},
    getServers: function() {
        this.set('data', Ember.Object.create({
            "Servers": [
                {
                "Name": "USWest",
                "CurrentTime": "1337",
                "processes": [
                    {
                        "Name": "apache.exe",
                        ...
                    }
                ]}
            ]
        }));
    }
});​

恕我直言,this.Processes应该在#each帮助程序中工作,所以这可能是一个错误。您是否能够更改从服务器获取的 JSON 的属性名称?否则,您可能会编写一个助手,在使用 JSON 之前将其属性名称小写...


另一个注意事项:Application#ready在您提供的 JSFiddle 中不起作用,因为您指定了要执行的 JS onDomReady(选择 JSFiddle 左上角的下拉菜单)。如果您将其更改为no wrap您可以Appready回调中访问。


关于命名的另一个注意事项:实例应命名为小写,类应命名为大写。所以它会App.serverOverview1 = Ember.View.create({ ... });在你的例子中。

于 2012-04-25T08:04:54.230 回答
2

Ember 尝试通过它是否具有大写属性来推断您的路径是绝对(全局)还是相对(本地)。在这种情况下,Ember 正在寻找Processes不存在的全局属性。正如@pangratz 指出的那样,简单的解决方案是使用小写字母。有关详细信息,请参阅http://www.emberist.com/2012/04/09/naming-conventions.html

于 2012-04-25T14:56:55.593 回答
0

这是我做的后处理方法:

function decapitalizeJSON(data, dataType) {
    var output = (dataType == undefined || dataType == '[object Object]') ? {} : [];
    var value, type;

    for(var key in data) {
        if(!data.hasOwnProperty(key)) {
            continue;
        }

        value = data[key];
        type = Object.prototype.toString.apply(value);

        if (type == '[object Array]' || type == '[object Object]') {
            output[key.charAt(0).toLowerCase() + key.substr(1)] = decapitalizeJSON(value, type);
        }
        else {
            output[key.charAt(0).toLowerCase() + key.substr(1)] = value;
        }
    }

    return output;
}

然而,它非常缓慢 - 不足为奇。需要hashasOwnProperty来防止它尝试复制 Ember 添加到 Array 对象的方法,并且它是递归的,以确保它对所有内容进行大写。在我的情况下,它可能可以优化为仅对数组进行大写,但随后您再次混合命名约定。

相反,我只是要求 API 供应商添加一个“emberHack”属性,如果通过,它会为我提供正确的 JSON Ember 期望并且已经被授予 - 但据说是一个“la脚”的要求。我可以向你保证,大多数 API 供应商不会像我的那样宽容。

于 2012-04-26T12:58:24.833 回答