External templates and “el” with Knockout and Requ

2019-05-10 19:17发布

问题:

I am trying to use Knockout ViewModels as self-contained "widgets" that can be placed into any (or multiple) DOM nodes on the page. I had an approach in Backbone that seemed to work well and I'm trying to convert the concept to Knockout.

In Backbone view I would do something like this, using the RequireJS text plugin to pull the template and inject it into the el:

define(['text!templates/myTemplate.html',], function(templateHTML){
    var view = Backbone.View.extend({

        initialize:function() {
            // yes I know the underscore templating stuff doesn't apply in Knockout
            this.template = _.template( templateHTML );
            this.render();
        },

        render:function( ) {
            // the $el is provided by external code. See next snippet
            this.$el.append(this.template(myData));
            return this;
        }

        // other view behavior here

    });

    return view;
});

And then some other piece of external code could place that view into an existing DOM node:

new MyBackboneView({el: $('#myExistingDivID')});

In Knockout, the closest I can find to this approach is to have the external code use the Text plugin to pull the template, inject it into the div, and then apply the KO bindings:

var mydiv = $('#myExistingDivID');
mydiv.html(myTemplateHTML);
ko.applyBindings(new MyKOViewModel(), mydiv[0]);

1 - Is there a recommended way in Knockout to have the ViewModel itself inject the external template HTML based on the equivalent of Backbone's "el" concept? The key is that the external (router-ish) code controls where the content will be placed, but the ViewModel controls the actual details of the content and where to get the template.

2 - If yes, should I take this approach, or am I abusing the way that Knockout and MVVM are intended to be used?

回答1:

You can override the default template source and then use that with the default render engine like

var stringTemplateEngine = new ko.nativeTemplateEngine();
stringTemplateEngine.makeTemplateSource = function (template) {
    return new StringTemplateSource(template);
};
ko.setTemplateEngine(stringTemplateEngine);

Quick example I did

http://jsfiddle.net/3CQGT/