foreach 中的自定义元素在淘汰赛中没有预期的模型

Custom element inside foreach have not expected model in knockout

淘汰赛的新手我正在尝试为自定义元素建立 POC。

模型很简单,一个 MainModel 包含一个 LinkModel 数组。

目标是遍历链接数组以显示每个 LinkModel 对象的 1 个自定义元素 "settings-view-link"。

function LinkModel(params) {
    var self = this;
    self.name = ko.observable(params.name);
}

function MainModel() {
    var self = this;
    self.links = ko.observableArray([
        new LinkModel({ name: "link1"}),
        new LinkModel({ name: "link2"})
    ]);
};

$(function () {
    //registration of the custom element
    ko.components.register('settings-view-link', 
    { 
      viewModel: LinkModel, 
      template: "<div><strong data-bind='text: name'></strong></div>" 
    });
    ko.applyBindings(new MainModel());
});
<div>
    <ul data-bind="foreach: links">
         <p data-bind="text: name"></p> <!-- handled correctly -->
         <settings-view-link></settings-view-link> <!-- handled not the way I expect-->
     </ul>
</div>

我看到的是,如果在自定义元素中我需要使用 $parent。让我的数据绑定按预期工作。使用

<div><strong data-bind='text: $parent.name'></strong></div>

而不是

<div><strong data-bind='text: name'></strong></div>

使我的链接名称出现在网页上。

我期望在自定义元素内部它处理一个 LinkModel 对象,但它不是,它在某种程度上是一个 "submodel"。 有人可以解释为什么我必须使用 $parent 吗?代码是错误的,但为什么?我真的希望在我的自定义元素中有一个 LinkModel 对象。

非常感谢

因为您的自定义组件指定了一个 viewModel 选项,所以 knockout 将为您创建该视图模型的一个新实例。您可以省略 属性,knockout 会将组件绑定到提供的参数:

Components usually have viewmodels, but they don’t necessarily have to. A component can specify just a template. In this case, the object to which the component’s view is bound is the params object that you passed to the component binding

来源:http://knockoutjs.com/documentation/component-binding.html#note-template-only-components

这个例子可能更好地解释了我的意思。第一个组件指定一个视图模型函数,该函数被实例化并绑定到组件实例。

第二个组件将$data作为参数传递,基本上用作模板。如果您不想自动创建新的视图模型,您可能只需要模板绑定。

var instanceCounter = 0;

var ViewModel = function() {
  this.nr = instanceCounter++;
}

ko.components.register('testComponent1', {
  viewModel: ViewModel,
  template: '<div data-bind="text: nr"></div>'
});

ko.components.register('testComponent2', {
  template: '<div data-bind="text: nr"></div>'
});


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


<section>
  <h2>New instance for each component</h2>
  <div data-bind='component: {
    name: "testComponent1"
}'></div>
  <div data-bind='component: {
    name: "testComponent1"
}'></div>
  <div data-bind='component: {
    name: "testComponent1"
}'></div>
</section>

<section>
  <h2>Same instance for each component</h2>
  <div data-bind='component: {
    name: "testComponent2",
    params: $data
}'></div>
  <div data-bind='component: {
    name: "testComponent2",
    params: $data
}'></div>
  <div data-bind='component: {
    name: "testComponent2",
    params: $data
}'></div>
</section>