使用 ViewModel 构造函数淘汰虚拟组合
Posted
技术标签:
【中文标题】使用 ViewModel 构造函数淘汰虚拟组合【英文标题】:Knockout virtual compose with ViewModel constructors 【发布时间】:2013-04-05 08:39:58 【问题描述】:我在使用 3 对 Views/ViewModels 进行虚拟 Knockout 组合时遇到了一些奇怪的功能
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 可以链接到具有自己的 menuItems 的子菜单。
问题出现在第二个ko compose
。 console.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
为什么会这样?
【问题讨论】:
您是否尝试在运行 foreach 循环之前检查您的 menuItems?类似的东西<span data-bind="text: ko.toJSON($data.menuItems)"></span>
<!-- ko foreach: data: menuItems -->
下一个想法:如果 menuItems 本身没有问题,这里是 Durandal 源代码中的 ko.compose
。 github.com/BlueSpire/Durandal/blob/master/App/durandal/… 在github.com/BlueSpire/Durandal/blob/master/App/durandal/… 周围设置断点应该有助于澄清事情。
我在ko foreach
前后放置了带有menuItems toJSON 的span,并且menuItems 的格式正确。因此,当切换到组合的 menuItem 上下文时,这些值会丢失或被覆盖。
【参考方案1】:
在对源代码进行深入研究和(不止)一点实验之后,以下方法奏效了:
<!-- ko compose: view:'settings/autoAttendant/menuItem' --><!--/ko-->
来自Durandal docs on compose
【讨论】:
现在你发现它是有道理的。已经有 ko.observablemenuItems
包含所有 new MenuItem(...)
,因此定义视图就是所需要的。不知道杜兰达尔这么聪明,谢谢分享。以上是关于使用 ViewModel 构造函数淘汰虚拟组合的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Xamarin 和 Autofac 将构造函数依赖项注入 ViewModel?
如何使用 Xamarin.Forms.DependencyService 注入具有构造函数注入的 ViewModel
在 viewmodel 的构造函数中调用异步方法加载数据有警告
如何使用带有两个构造函数的viewmodel的Unity框架显示子窗口?