我有一堆处理游戏业务逻辑的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>
答案 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);
};