使用ViewModel构造函数击倒虚拟组合

Knockout virtual compose with ViewModel constructors

本文关键字:虚拟 组合 ViewModel 构造函数 使用      更新时间:2023-09-26

我有一些奇怪的功能与虚拟Knockout组成使用3对视图/ViewModels

autoAttendant.js

define(['durandal/app', 'viewmodels/settings/autoAttendant/menu'], function(app, Menu){
    return function() {
        var self = this;
        self.attendant = ko.observable();
        self.activate = function() {
            self.autoAttendant(new Menu());
        };
    };
});

autoAttendant.html

<div id="content_pane" class="pushed_right">
    <div class="content_box">
        <h1>Attendant</h1>
        <!-- ko compose: 'viewmodels/settings/autoAttendant/menu' --><!--/ko-->
    </div>
</div>

menu.js

define(['durandal/app', 'viewmodels/settings/autoAttendant/menuItem'], function(app, MenuItem) {
    return function() {
        var self = this;
        self.menuItems = ko.observableArray([
            new MenuItem('val1', 'label1'),
            new MenuItem('val2', 'label2'),
            // etc...
        ]);
    };
});

menu.html

<div class="list">
    <div class="box_item master">
        <!-- html content -->
    </div>
    <!-- ko foreach: { data: menuItems } -->
        <!-- ko compose: 'viewmodels/settings/autoAttendant/menuItem' --><!--/ko-->
    <!-- /ko -->
</div>

menuItem.js

define(['durandal/app'], function(app) {
    var menuItem =  function(val, label, active) {
        var self = this;
        console.log('val:', val, 'label:', label, 'active:', active); // purely for testing purposes
        var _val = val || 'default_val',
            _label = label || 'default_label',
            _active = active || false;
        self.val = ko.observable(_val);
        self.label = ko.observable(_label);
        self.active = ko.observable(_active);
    };
    return menuItem;
});

menuItem.html

<div class="level">
    <div class="box_item clickable">
        <!-- html content -->
    </div>
</div>

这些组合在一起代表一个单独的页面,在设置中显示菜单和菜单的子项。

Menu和MenuItem 必须从伴随的View/ViewModel中分离出来,因为菜单本身是递归的,并且MenuItem可以链接到带有自己的菜单项的子菜单。

问题出现在第二个ko composeconsole.log出现了3次,前2次显示了向menu.js中的MenuItem构造器传递参数的正确方式:

val: val1 label: label1 active: undefined

在最后的console.log打印出来时,已经传递的参数被覆盖,如下所示:

val: <!-- ko compose: 'viewmodels/settings/autoAttendant/menuItem' --><!--/ko--> label: Object {model: "viewmodels/settings/autoAttendant/menuItem", bindingContext: L.b.z, activeView: null} active: undefined

为什么会发生这种情况?

经过对源代码的深入研究和(不止)一点实验后,下面的方法奏效了:

<!-- ko compose: {view:'settings/autoAttendant/menuItem'} --><!--/ko-->

From Durandal docs on compose