使用 'with' 绑定的 Knockout js 组件未按预期运行

Knockout js component using 'with' binding not behaving as expected

我在 JSFiddle 中设置了以下代码:https://jsfiddle.net/ktce56hr/2/

var RootViewModel = function() {
    var self = this;
    this.rootText = ko.observable('default text');
    this.rootFunc = function() {
        alert("root func!");
    };
}

ko.components.register('root', {
    viewModel: function(model) {
        var self = this;
        this.rootViewModel = model;
        this.title = ko.observable('default title');
    },
    template: { element: 'root_template' }
});

$(function () {
    ko.applyBindings(new RootViewModel());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>

<div data-bind="component: { name: 'root', params: { model: $root } }"></div>

<script id="root_template" type="text/html">
    <div>
        <span data-bind="text: title"></div>
        <div data-bind="with: rootViewModel">
            <input type="text" data-bind="value: rootText" />
            <button data-bind="click: rootFunc">Go</button>
        </div>
    </div>
</script>

当此代码为 运行 时,我收到以下错误:

Uncaught ReferenceError: Unable to process binding "with: function (){return rootViewModel }"
Message: Unable to process binding "value: function (){return rootText }"
Message: rootText is not defined

有人可以解释为什么我不能在我的组件视图模型上使用 'rootViewModel' 属性 设置绑定上下文吗?

您正在这样声明组件实例:

<div data-bind="component: { name: 'root', params: { model: $root } }"></div>

params 将是视图模型构造函数的第一个参数。对于视图模型构造函数,它看起来像这样:

"model": {
  "rootText": "default text"
}

它的视图模型 returns 将是这样的:

{
  "rootViewModel": {
    "model": {
      "rootText": "default text"
    }
  },
  "title": "default title"
}

当然,在您的视图中访问 title 是可行的。但是在 with: rootViewModel 里面它不会包含 rootText.

修复很简单:

<div data-bind="component: { name: 'root', params: $root }"></div>

var RootViewModel = function() {
    var self = this;
    this.rootText = ko.observable('default text');
    this.rootFunc = function() {
        alert("root func!");
    };
}

ko.components.register('root', {
    viewModel: function(model) {
        var self = this;
        this.rootViewModel = model;
        this.title = ko.observable('default title');
    },
    template: { element: 'root_template' }
});

$(function () {
    ko.applyBindings(new RootViewModel());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>

<div data-bind="component: { name: 'root', params: $root }"></div>

<script id="root_template" type="text/html">
    <div>
        <span data-bind="text: title"></div>
        <div data-bind="with: rootViewModel">
            <input type="text" data-bind="value: rootText" />
            <button data-bind="click: rootFunc">Go</button>
        </div>
    </div>
</script>

P.S.: rootFunc 仍然存在类似的问题,但我相信您可以解决这个问题。