在 requirejs 加载的 knockout.js 组件中丢失视图模型上下文

Losing view model context in a knockout.js component loaded by requirejs

require js加载的knockout js组件有一个奇怪的问题。 组件很简单。

define([
    'jquery',
    'knockout'
], function ($, ko) {


    function ViewModel(params) {
        var self = this;
        this.test = 'test';
    }

    ViewModel.prototype.fetchData = function() {
        var self = this;
        console.log(this.test);
    };

    ViewModel.prototype.init = function() {
        console.log(this.test);
        this.fetchData();
    };

    ko.components.register('my-component', {
        viewModel: ViewModel,
        template: '<span data-bind="template: { afterRender: init }"></span>'
    });

});

现在,模板绑定可以调用视图模型init方法,但是这个方法本身不能访问fetchData 方法,因为在方法内部 this 绑定到 Window 对象而不是视图模型。

我准备了一个fiddle来显示错误情况:http://jsfiddle.net/ask4artur/3f6jsa4m/47/

相信 knockout 不会自动调用$data 的this-context 中的afterRender 方法。您可以使用 bind$data 设置为 this,如下所示:

data-bind="template: { afterRender: init.bind($data) }

var i = 0;

var ViewModel = function() {
   this.nr = "Instance " + i++; 
}

ViewModel.prototype.logNr = function() {
    console.log(this.nr);
};

ko.components.register('test', {
    viewModel: ViewModel,
    template: '<div data-bind="template: { name: \'testTemplate\', afterRender: logNr.bind($data) }"></div>'
});

ko.applyBindings();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>


<script type="text/html" id="testTemplate">
  <div data-bind="text: nr, click: logNr"></div>
</script>