Tay lái / Bộ ria mép - Có cách nào được xây dựng để lặp qua các thuộc tính của một đối tượng không?


216

Như tiêu đề của câu hỏi, có một cách ria mép / tay cầm vòng lặp thông qua một thuộc tính đối tượng ?

Vì vậy

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
}

Sau đó tôi có thể làm gì đó trong công cụ mẫu tương đương với

for(var prop in o)
{
    // with say, prop a variable in the template and value the property value
}

?

Câu trả lời:


448

Hỗ trợ tích hợp kể từ Tay cầm 1.0rc1

Hỗ trợ cho chức năng này đã được thêm vào Handlebars.js, do đó không cần thêm người trợ giúp bên ngoài.

Làm thế nào để sử dụng nó

Đối với mảng:

{{#each myArray}}
    Index: {{@index}} Value = {{this}}
{{/each}}

Đối với các đối tượng:

{{#each myObject}}
    Key: {{@key}} Value = {{this}}
{{/each}}

Lưu ý rằng chỉ các thuộc tính vượt qua hasOwnPropertybài kiểm tra sẽ được liệt kê.


2
@Rafi: người ta không thể hiểu nhiều về điều đó mà không biết cấu trúc dữ liệu của bạn.
Jon

3
@Rafi: ý bạn không phải là {{this.title}}?
nevyn

2
@qodeninja: Đơn giản: giống như cách bạn đề cập đến các giá trị trong các ví dụ trên - với {{#each this}}. Sự lựa chọn thuật ngữ của bạn cũng khó hiểu (điều gì làm cho một đối tượng "cấp cao nhất" và một đối tượng khác không phải là "khóa" được xác định trước chính xác là gì? V.v.), vì vậy bạn có thể muốn xem lại các khái niệm này.
Jon

1
Nếu không nhầm thì chỉ với v1.1.0, điều này có sẵn, nhưng câu trả lời tuyệt vời cảm ơn.
Đổi mới Sirotins

2
Làm thế nào để bạn làm điều này chỉ cho một danh sách trắng tài sản cụ thể?
Marco Prins

70

Nó thực sự khá dễ dàng để thực hiện như một người trợ giúp:

Handlebars.registerHelper('eachProperty', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({property:prop,value:context[prop]});
    }
    return ret;
});

Sau đó sử dụng nó như vậy:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}

2
Có vẻ tốt, bạn có cần thêm kiểm tra hasOwnProperty bên trong vòng lặp để bạn không lặp lại các thuộc tính nguyên mẫu không?
khỉ

Giải pháp tuyệt vời @Ben. Trong trường hợp bất cứ ai đang cố gắng sử dụng điều này với Ember, hãy xem câu trả lời của tôi dưới đây để biết giải pháp để nó hoạt động.
cá chuồn

27

EDIT: Tay lái hiện có một cách tích hợp để thực hiện điều này; xem câu trả lời được chọn ở trên Khi làm việc với Mustache đơn giản, dưới đây vẫn được áp dụng.

Bộ ria mép có thể lặp đi lặp lại trên các mục trong một mảng. Vì vậy, tôi khuyên bạn nên tạo một đối tượng dữ liệu riêng được định dạng theo cách Mustache có thể làm việc với:

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
},
mustacheFormattedData = { 'people' : [] };

for (var prop in o){
  if (o.hasOwnProperty(prop)){
    mustacheFormattedData['people'].push({
      'key' : prop,
      'value' : o[prop]
     });
  }
}

Bây giờ, mẫu Mustache của bạn sẽ giống như:

{{#people}}
  {{key}} : {{value}}
{{/people}}

Kiểm tra phần "Danh sách không trống" tại đây: https://github.com/janl/mustache.js


1
Đã kết thúc với đề xuất của bạn vì tôi cần phải vượt qua một số thuộc tính phụ bổ sung. Cảm ơn đã giúp đỡ!
Ben

Cảm ơn rất nhiều, ý tưởng của bạn đã giúp tôi tiết kiệm một ngày khác để tìm kiếm các lựa chọn thay thế. Dòng này là khóa mustacheFormattedData = {'people': []};
Matt

Làm thế nào bạn sẽ làm điều này với một loạt các đối tượng "o"?
red888

4

Đây là câu trả lời của @ Ben được cập nhật để sử dụng với Ember ... lưu ý bạn phải sử dụng Ember.getvì ngữ cảnh được truyền vào dưới dạng Chuỗi.

Ember.Handlebars.registerHelper('eachProperty', function(context, options) {
  var ret = "";
  var newContext = Ember.get(this, context);
  for(var prop in newContext)
  {
    if (newContext.hasOwnProperty(prop)) {
      ret = ret + options.fn({property:prop,value:newContext[prop]});
    }
  }
  return ret;
});

Bản mẫu:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}

Cảm ơn @flynfish. bối cảnh là một chuỗi trong Ember ?? có vẻ như .. hơi kỳ quặc
Ben

Phải, tôi không thực sự chắc chắn vì tôi mới biết về Ember và vẫn đang cố gắng tìm đường xung quanh nó.
cá ruồi

1

Câu trả lời của @ Amit là tốt bởi vì nó sẽ hoạt động trong cả Mustache và Tay cầm.

Theo như các giải pháp chỉ dành cho Tay cầm, tôi đã thấy một vài giải pháp và tôi thích trình each_with_keytrợ giúp khối tại https://gist.github.com/1371586 là tốt nhất.

  • Nó cho phép bạn lặp lại theo nghĩa đen của đối tượng mà không phải cấu trúc lại chúng trước, và
  • Nó cho phép bạn kiểm soát những gì bạn gọi là biến chính. Với nhiều giải pháp khác, bạn phải cẩn thận về việc sử dụng các khóa đối tượng có tên 'key', hoặc 'property', v.v.

Đẹp tìm thấy. Chỉ là một cảnh báo cho những người đọc khác: người trợ giúp "key_value" trong ý chính này có một lỗi trong đó. Đọc các bình luận để biết cách khắc phục.
sirentian

0

Cảm ơn giải pháp của Ben, trường hợp sử dụng của tôi chỉ hiển thị các trường cụ thể theo thứ tự

với đối tượng

Mã số:

    handlebars.registerHelper('eachToDisplayProperty', function(context, toDisplays, options) {
    var ret = "";
    var toDisplayKeyList = toDisplays.split(",");
    for(var i = 0; i < toDisplayKeyList.length; i++) {
        toDisplayKey = toDisplayKeyList[i];
        if(context[toDisplayKey]) {
            ret = ret + options.fn({
                property : toDisplayKey,
                value : context[toDisplayKey]
            });
        }

    }
    return ret;
});

Đối tượng nguồn:

   { locationDesc:"abc", name:"ghi", description:"def", four:"you wont see this"}

Bản mẫu:

{{#eachToDisplayProperty this "locationDesc,description,name"}}
    <div>
        {{property}} --- {{value}}
    </div>
    {{/eachToDisplayProperty}}

Đầu ra:

locationDesc --- abc
description --- def
name --- ghi

0

Đây là một hàm trợ giúp cho mustacheJS, không định dạng trước dữ liệu và thay vào đó nhận nó trong khi kết xuất.

var data = {
    valueFromMap: function() {
        return function(text, render) {
            // "this" will be an object with map key property
            // text will be color that we have between the mustache-tags
            // in the template
            // render is the function that mustache gives us

            // still need to loop since we have no idea what the key is
            // but there will only be one
            for ( var key in this) {
                if (this.hasOwnProperty(key)) {
                    return render(this[key][text]);
                }
            }
        };
    },

    list: {
        blueHorse: {
            color: 'blue'
        },

        redHorse: {
            color: 'red'
        }
    }
};

Bản mẫu:

{{#list}}
    {{#.}}<span>color: {{#valueFromMap}}color{{/valueFromMap}}</span> <br/>{{/.}}
{{/list}}

Đầu ra:

color: blue
color: red

(thứ tự có thể là ngẫu nhiên - đó là bản đồ) Điều này có thể hữu ích nếu bạn biết yếu tố bản đồ mà bạn muốn. Chỉ cần coi chừng các giá trị giả.


-1

Tôi đã sử dụng phiên bản 1.0.beta.6tay lái cũ , tôi nghĩ ở đâu đó trong 1.1 - 1.3 chức năng này đã được thêm vào, vì vậy việc cập nhật lên 1.3.0 đã giải quyết được vấn đề, đây là cách sử dụng:

Sử dụng:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.