【问题标题】:Knockoutjs and "subclassing" of view modelsKnockoutjs 和视图模型的“子类化”
【发布时间】:2014-05-28 20:36:18
【问题描述】:

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

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

根据不同的客户类型,我将有不同的编辑视图模型,在 Caliburn micro 中,它会根据视图模型的类型自动呈现正确的视图,类型在 JS 中当然不存在,但你能以某种方式实现这一点淘汰赛?

【问题讨论】:

  • 你想实现这样的目标吗:stackoverflow.com/questions/6706281/…
  • 不是真的不行,我想根据viewmodel的“类型”将Edit ViewModel绑定到不同的View(不同的html模板)。

标签: knockout.js


【解决方案1】:

感谢 Mike,您的解决方案并不完全符合我的需要,虽然我正在做类似的服务器端操作,但我们的 json-objects 是从 CQRS 读取模型存储库中读取的。

事实证明,命名模板是我所追求的。这是一个展示我所做的小小提琴(在我们的真实场景中,子模型的属性将在实际的客户对象上)

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

更新: 刚刚看到这个答案得到了赞成。有更优雅的方法,例如使用我的 Convention over configuration library found here

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

它对使用该类型的模板有一个约定,因此请使用您喜欢的 OO 模式,例如这个

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

定义不同的类型,重要的是它们以 ModelViewModel

为后缀

模板应具有相同的名称但后缀为View

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

http://jsfiddle.net/JKXaX/5

【讨论】:

    【解决方案2】:

    我做了一些类似于我认为你想做的事情。

    我所做的是在服务器上创建视图模型,将它们序列化为 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);
    });
    

    嗯。原来是一段代码。这就是我如何在服务器和客户端之间架起桥梁,同时仍然能够根据类型名称等选择模型。它还允许我在服务器上定义数据结构,同时在剔除视图模型中定义表示特定的行为。映射插件有点神奇,但一个缺点是您在淘汰视图模型中看不到数据结构,但我接受了这一点。此外,请注意名称的大小写不同,如果您不能忍受 Newtonsofts Json 序列化程序在序列化时可以更改大小写。我选择不这样做,因为它可以帮助我查看来自服务器的内容以及我在视图模型中定义的内容。

    【讨论】:

    • 我使用单独的 html 块作为模板(不是 jquery/ko 模板)并使用 with 绑定,就像 with: MyFirstEditModel 一样。对于该块中的常见内容,您可以调用 ko 模板。
    • 嗯,好吧,我希望他们有一些内置的东西,感觉就像一个非常标准的 MVVM 行为,你想要动态绑定视图模板......哦,好吧
    • 您可以从代码中调用 ko 模板,这可能对您的情况有所帮助。
    • 你的意思是 ko.applyBindings(model, htmlElement)?这在这种情况下不好,因为它将获取该元素中的模板数据并在该元素中呈现模型的内容。
    • 不,就像这个问题一样:stackoverflow.com/questions/9641063/…
    猜你喜欢
    • 2015-10-31
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 2012-06-08
    • 2015-03-05
    • 2013-12-26
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多