遍历 Meteor.js 中的嵌套对象并将结果插入 table

Iterate through nested objects in Meteor.js and insert results into table

我正在尝试在 Meteor.js 中制作一个 RuneScape hiscores 检查器。我现在成功地解析了来自他们 API 的数据并将其保存为对象(您可以在此处查看正在运行的应用程序:http://rs-hiscores.meteor.com/)。这是我的服务器代码:

var cheerio = Meteor.npmRequire('cheerio');

var BASE_SKILLS = [ 
  'overall', 'attack', 'defence', 'strength', 'hitpoints', 'ranged',
  'prayer', 'magic', 'cooking', 'woodcutting', 'fletching', 'fishing',
  'firemaking', 'crafting', 'smithing', 'mining', 'herblore', 'agility', 
  'thieving', 'slayer', 'farming', 'runecrafting', 'hunter', 'construction'
];

var skills = {
  'osrs': BASE_SKILLS,
  'rs3': BASE_SKILLS.concat('summoning', 'dungeoneering', 'divination')
};

var urls = {
  'osrs': 'http://services.runescape.com/m=hiscore_oldschool/index_lite.ws?player=',
  'rs3': 'http://hiscore.runescape.com/index_lite.ws?player='
};

Meteor.methods({  
  lookup: function(player, game) {
    if (!urls.hasOwnProperty(game)) {
      game = 'rs3';
    }
    var url = urls[game].concat(encodeURIComponent(player));
    result = Meteor.http.get(url);
    $ = cheerio.load(result.content);
    body = $.html();
    parsed = Meteor.call('parseStats', body, skills[game]);
    return parsed;
  },
  parseStats: function(raw, skillsList) {
    var stats = raw.split('\n').slice(0, skillsList.length);
    var statsObj = { };
    stats.forEach(function(stat, index) {
      var chunk = stat.split(',');
      statsObj[skillsList[index]] = {
        rank: +chunk[0],
        level: +chunk[1],
        xp: +chunk[2]
      };
    });
    return statsObj;
  }
});

在我的客户端代码中,我通过在函数内提供玩家名称作为参数来手动测试查找方法:

Meteor.call('lookup', 'zezima', 'rs3', function(error, result) {

  if (error) {
    console.error(error);
  }

  console.log(result);

  Session.set("data", result);

});

Template.rawdata.helpers({

  getData: function() {
    return Session.get("data");
  }

});

控制台结果:

{
    agility: {
        level: 99,
        rank: 174,
        xp: 100234567
    },

    attack: {
        level: 99,
        rank: 601,
        xp: 127370193
    },

    construction: {
        level: 99,
        rank: 119,
        xp: 141170001
    },

    and so on...
}

显然,当我在 html 的模板中调用 getData 并渲染它时,它显示:[object Object]。所以我想以某种方式遍历对象并将它们插入 table,看起来像这样:

<table id="rs-hiscores">
    <thead>
        <tr>
            <th>Skill name</th>
            <th>Rank</th>
            <th>Level</th>
            <th>Xp</th>
        </tr>
    </thead>
    <tbody id="rs-hiscore-data">
        <tr>
            <td>Agility</td>
            <td>99</td>
            <td>174</td>
            <td>109317063</td>
        </tr>
        <tr>
            <td>Attack</td>
            <td>99</td>
            <td>601</td>
            <td>127370193</td>
        </tr>
        <tr>
            <td>Construction</td>
            <td>99</td>
            <td>119</td>
            <td>141170001</td>
        </tr>

        ...and so on ...
    </tbody>
</table>

我该怎么做?还有 - 是否可以按照 BASE_SKILLS 中技能的相同顺序对结果进行排序?预先感谢您的帮助。

好的,所以您需要按照 BASE_SKILLS 的顺序将数据放在一个合适的数组中,使用 Underscore 将技能从您的数据映射到一个新数组,您的 getData 助手应该是这样的:

var data = Session.get('data');
var array = _.map( BASE_SKILLS, function(skillName){
  var skill = data[skillName]
  return {
           name: skillName,
           rank: skill.rank,
           level: skill.level,
           xp: skill.xp
         };
});
return array;

这样就形成了一个整洁的数组,如下所示:

[
  {
    name: "overall",
    rank: 99,
    level: 174,
    xp: 109317063
  },
  {
    name: "attack",
    rank: 23,
    level: 201,
    xp: 256311563
  },
  ...etc
]

然后您需要以您想要的方式将这些值输入 html。

<table id="rs-hiscores">
<thead>
    <tr>
        <th>Skill name</th>
        <th>Rank</th>
        <th>Level</th>
        <th>Xp</th>
    </tr>
</thead>
<tbody id="rs-hiscore-data">
  {{#each getData}}
    <tr>
      <td>{{name}}</td>
      <td>{{rank}}</td>
      <td>{{level}}</td>
      <td>{{xp}}</td>
    </tr>
   {{/each}}
</tbody>
</table>

不过,您的 table 中会有小写键,overall 而不是“Overall”,但是为了获得好听的名字,您可以制作一个字典辅助函数,将一个替换为另一个像这样:{{getNiceName name}}.