Knockoutjs和视图模型的“子类化”

时间:2012-03-16 09:37:10

标签: knockout.js

在其他框架的其他MVVM API中,例如Caliburn Micro for WPF,您可以使用子类视图模型。作为一个例子,我有这个视图模型

Customer
Id : int
Selected : bool
Name : string
Edit : ViewModel

根据不同的客户类型,我将有不同的Edit ViewModel,在Caliburn micro中,它会自动呈现正确的视图,具体取决于ViewMOdel的类型,类型是JS中不存在的类型,但是你能否在某种程度上实现这一点敲除?

2 个答案:

答案 0 :(得分:1)

感谢Mike,你的解决方案并不是我所需要的,我做了类似的服务器端,但我们的json对象是从CQRS读取模型库中读取的。

事实证明,命名模板就是我所追求的.Heres是一个小小的小提琴,显示我做了什么(在我们的实际场景中,子模型的属性将在实际的客户对象上)

http://jsfiddle.net/Z7gMN/1/

<强>更新 刚刚看到这个答案得到了提升。有更优雅的方法,例如使用我在这里找到的配置库上的约定

https://github.com/AndersMalmgren/Knockout.BindingConventions

它有一个使用该类型的模板的约定,所以使用你喜欢的OO模式

http://ejohn.org/blog/simple-javascript-inheritance/

定义不同的类型,重要的是它们后缀为模型 ViewModel

模板应具有相同的名称,但后缀为查看

<script type="text/html" id="MyView">
    <input data-name="myValue" />
</script>  

http://jsfiddle.net/JKXaX/5

答案 1 :(得分:0)

我做了类似于我想你想做的事情。

我所做的是在服务器上创建视图模型,将它们序列化为json并使用映射插件创建Knockout视图模型。

我在C#中有一个公共基类,并且有一些具有各种数据结构的实现类。然后我只在淘汰赛中定义行为。

这样的事情:

public abstract MyBase : IDefineMyBase {
    public string Type { get { return this.GetType().Name; } }
}

public class MyFirstEditModel : MyBase {
    public string Something { get; set; }
}

我使用ASP.NET MVC来实现淘汰:

public ActionResult MyAction() {
   var model = {
       EditModels = new IDefineMyBase[] {
           new MyFirstEditModel {
               Something = "Some thing"
           },
           ... other implementations
       }
   };

   // AsJson is a serialization extension method
   return View("MyView", (object)model.AsJson()); 
}

在Knockout中,我这样使用它:

// This is a behaviour base "template" that will be applied for all editmodels
var editModel = function(data) {
    // Map the edit model specific data to *this*
    ko.mapping.fromJS(data, {}, this);

    // Apply implementation specific behaviour to this instance of the model
    eval(this.Type() + '(this)'); // example: MyFirstEditModel(this);
}

// This is specific behaviour for MyFirstEditModel
var MyFirstEditModel = function(base) {
    base.someBindableSpecificFunction = function() {
        // You can use data from the implementation here.
        alert(base.Something());
    };
}

// This is the base view model where you can have all the main functionality
var viewModel = function(base) {
    ko.utils.arrayForEach(data.EditModels(), function (editModel) {
        s.Parent = base;
        // example: base.MyFirstEditModel = editModel;
        eval('base.' + s.Type() + ' = editModel');
    });
}

// This is mapping instructions
var mapping = {
    'EditModels': {
        create: function (options) {
            return new editModel(options.data);
        }
    }
};

$(document).ready(function () {
    // Map the server side model to knockout
    var mapped = ko.mapping.fromJS(@Html.Raw(Model), mapping, vm);
    // Add behaviour to the mapped data
    viewModel(mapped);
    ko.applyBindings(vm);
});

嗯。结果证明是一些代码。这就是我如何弥合服务器和客户端之间的差距,同时仍然能够根据类型名称和类似的东西选择模型。它还允许我在服务器上定义数据结构,同时在挖空视图模型中定义表示特定的行为。映射插件有点神奇,但一个缺点是你没有在knockout视图模型中看到数据结构,但我已经接受了。另外,请注意名称的外壳不同,如果你不能忍受,Newtonsofts Json序列化器在序列化时可以更换外壳。我选择不这样做,因为它帮助我看到服务器的内容以及我在视图模型中定义的内容。