Extending knockout viewmodels with prototype

2019-08-11 09:02发布

问题:

If a viewmodel is already defined, either manually or automatically with mapping plugin, is there any problem to "extend" (add properties/functions) the viewmodel later in the code by using prototype?

I'm aware of the create callback of mapping plugin, I just want to know if there are any implications of using prototype instead? The reason I'm asking is because I'm generating large parts of the viewmodels from server side code, but sometimes need to extend the viewmodel later than at initial generation.

回答1:

I don't think there is any problem with this, I work with a large deep view model graph instantiated via the mapping plugin from correspondingly structured JSON and I use prototypes to define an "AbstractViewModel" with useful properties and toJSON "overrides" among other things.



回答2:

There is no problem with this. Just make sure that the view responds appropriately when there's no data in that particular field in the viewModel.



回答3:

There seems to be a couple ways of going about this.

For one, you can take a single object view model and utils.extend them via prototype:

ko.utils.extend(ViewModelClass.prototype, {
    newPrototype1: function () { ... },
    newPrototype2: function () { ... }
}

Or, you can add an extender to knockout and invoke it via the observable object itself: (http://knockoutjs.com/documentation/extenders.html)

ko.extenders.numeric = function(target, precision) {
    ...details in link above...
}

...
self.NumericProperty = ko.observable(data).extend({ numeric: 0 });
...

Or create a function that is available to all instances of an observable, observableArray, computed... (http://knockoutjs.com/documentations/fn.html)

ko.observable.fn.filterByProperty = function(propName, matchValue) {
    return ko.computed(function() {    
        ...details in link above...
    }, this);
}

I tend to use combinations of these. I like extending prototypes of View Models in a separate file from the VMs and Mappings, so I have a structure like

  • ViewModel(s).js
  • ViewModel(s).Mappings.js
  • ViewModel(s).Prototypes.js

As you'll see, the timespan between these 'answers' is rather large, so some things have changed yet some things remain the same.