Knockout.js和自定义类

时间:2013-08-30 07:19:40

标签: javascript knockout.js coffeescript

我有一堆处理游戏业务逻辑的JavaScript类。这些类与特定框架无关,应保持不变。他们代表球员,他们的属性和可能的​​行动。我现在想要使用KnockoutJS来获得一个全新的视图,这个视图非常重要,并且具有此游戏角色类的多个实例。问题是我的KnockoutJS驱动的视图模型和游戏类之间的交互,因为后者没有得到更新。

这是CoffeeScript中游戏类的摘录:

class AnimaCharacter 
    constructor: (options) ->
        {
            @name,
            @level,
            @characteristics,
            @lifePoints
        } = options

        # ...

        if not @lifePoints
            @lifePoints = this.baseLifePoints()


    baseLifePoints: ->
        20 + @characteristics.constitution * 10

如您所见,有一些影响其他价值观的基本特征。例如,在此摘录中,characteristics.constitution值会影响baseLifePoints()的结果。还有其他一些,在幕后更复杂的计算,例如在战斗中。

现在,我的简单视图包含KnockoutJS模板:

<script id="card-template" type="text/html">
  <div class="charactercard">
    <div class="character-name">
      <h1>
        <span data-bind="text: name"></span><input type="text" data-bind="value: name" />
        <a href="#"><span class="ui-icon ui-icon-pencil character-action"></span></a>
        <a href="#"><span class="ui-icon ui-icon-copy character-action"></span></a>
      </h1>
    </div>
    <dl>
      <dt>Life Points</dt>
      <dd><span data-bind="text: baseLifePoints"></span></dd>
  </div>
</script>

但是,我不知道如何以允许我更新字符类实例的方式设置视图模型。我可以想出一个像这样的简单模型:

class CharacterModel
    constructor: (character) ->
        @character = ko.observable(character)
        @name = ko.observable(character.name)
        @baseLifePoints = ko.observable(character.baseLifePoints())

但是,当我更新character.name时,这不会更新实际baseLifePoints()或影响character.characteristics.constitution

更新字符实例而不将其完全转换为KnockoutJS视图的最佳方法是什么?我是否需要以自定义方式订阅更改事件?有没有办法透明地创建字符类实例的选择属性的“引用”? (我不是一个JavaScript人,所以我在这里借用了C ++中的术语“参考”。)

ko.mapping.fromJS()不是一个选项,因为它将characteristics.constitution属性的类型更改为自定义的KnockoutJS函数,这意味着我不能像在整个类的其余部分那样调用它。 / p>

1 个答案:

答案 0 :(得分:1)

您必须订阅Knockoutside上的更改并手动更新成员。你可以这样做

KnockoutViewModel = function() {
   //Knockout members goes here

   ko.computed(function() {
      var subscriber = ko.toJSON(this); //Just for sub

      for(var index in this) {
         if(myOtherModel[index] !== undefined) {
            myOtherModel[index] = ko.unwrap(this[index]);
         }
      }
   }, this);
};

http://jsfiddle.net/LMy4r/1/