我有一堆处理游戏业务逻辑的 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 函数,这意味着我不能像在整个课程中那样调用它。