我想提出一种在 MVVVM 中使用模态的不同方法。在 MVVM 中,ViewModel 是 View 的数据,View 负责 UI。如果我们检查这个提议:
this.detailedEmployee = ko.observable({}),
var self = this;
this.showDetails = function(employee){
self.detailedEmployee(employee);
$("#dialog").dialog("show"); //or however your dialog works
}
我非常同意this.detailedEmployee = ko.observable({}),但我非常不同意这句话:$("#dialog").dialog("show");。这段代码放在 ViewModel 中并显示模态窗口,实际上它是 View 的责任,所以我们搞砸了 MVVM 方法。我想说这段代码将解决您当前的任务,但将来可能会导致很多问题。
- 关闭弹出窗口时,您应该将
detailedEmployee 设置为undefined 以使您的主ViewModel 处于一致状态。
- 关闭弹出窗口时,您可能希望在应用程序中使用另一个模态组件时进行验证并放弃关闭操作
对我来说,这些点非常关键,所以我想提出一个不同的方法。如果我们“忘记”您需要在弹出窗口中显示数据,绑定with 可以解决您的问题。
this.detailedEmployee = ko.observable(undefined);
var self = this;
this.showDetails = function(employee){
self.detailedEmployee(employee);
}
<div data-bind="with: detailedEmployee">
Data to show
</div>
如您所见,您的 ViewModel 不知道应如何显示数据。它只知道应该显示的 data。 with 绑定只有在定义了detailedEmployee 时才会显示内容。接下来,我们应该找到一个类似于with 的绑定,但它会在弹出窗口中显示内容。让我们将其命名为modal。它的代码是这样的:
ko.bindingHandlers['modal'] = {
init: function(element) {
$(element).modal('init');
return ko.bindingHandlers['with'].init.apply(this, arguments);
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var returnValue = ko.bindingHandlers['with'].update.apply(this, arguments);
if (value) {
$(element).modal('show');
} else {
$(element).modal('hide');
}
return returnValue;
}
};
如您所见,它在内部使用with 插件,并根据传递给绑定的值显示或隐藏弹出窗口。如果已定义 - '显示'。如果不是 - '隐藏'。它的用法如下:
<div data-bind="modal: detailedEmployee">
Data to show
</div>
您唯一需要做的就是使用您最喜欢的模态插件。我准备了一个带有 Twitter Bootstrap 弹出组件的示例:http://jsfiddle.net/euvNr/embedded/result/
在这个例子中,自定义绑定更强大一些;您可以订阅 onBeforeClose 事件并在需要时取消此事件。希望这会有所帮助。