【问题标题】:$component incorrect within foreach binding inside a KO component$component 在 KO 组件内的 foreach 绑定中不正确
【发布时间】:2015-07-22 18:24:01
【问题描述】:

JS Fiddle 显示问题:http://jsfiddle.net/davetropeano/58vm9r6g/7/

我有一个呈现可观察数组的自定义组件。列表元素是只读的,我试图支持让用户删除元素。

这是模板:

<template id="kv-list">
<input type="text" placeholder="key" data-bind="textInput: k">
<input type="text" placeholder="value" data-bind="textInput: v">
<button data-bind="click: add">Add</button><br>

<table>
    <thead>
        <tr>
            <th data-bind="text: keyHeading"></th>
            <th data-bind="text: valueHeading"></th>
            <th></th>
        </tr>
    </thead>
    <tbody  data-bind="foreach: items">
        <tr>
            <td data-bind="text: k"></td>
            <td data-bind="text: v"></td>
            <td><a href="#" data-bind="click: $component.delete">delete</a></td>
        </tr>
    </tbody>
</table>

以及 ViewModel 和注册码:

函数 KV(k, v) { 自我=这个; 自我.k = k; 自我.v = v; } 功能 KVPairList(参数){ this.items = params.items; this.keyHeading = params.keyHeading || '钥匙'; this.valueHeading = params.valueHeading || '价值'; this.k = ko.observable(); this.v = ko.observable(); } KVPairList.prototype.add = function () { this.items.push(new KV(this.k(), this.v())); }; KVPairList.prototype.delete = 功能(项目){ this.items.remove(item); }; 功能虚拟机(参数){ this.title = params && params.heading ? params.heading : 'KO 组件示例'; this.variants = ko.observableArray(); } ko.components.register('kvlist', { 视图模型:KVPairList, 模板: { 元素:'kv 列表' } }); ko.components.register('page-main', { 视图模型:VM, 模板:{元素:'包装器'} }); ko.applyBindings();

添加到可观察数组可以正常工作。但是,如果您在其中一行上单击删除,则会出现错误:

Uncaught TypeError: Cannot read property 'remove' of undefined

看起来正在发生的事情是 $component 不是组件视图模型的上下文 - 它只是 foreach 绑定中的项目。我试过 $parent 也有同样的效果。

有没有办法在 foreach 循环中访问组件的视图模型?

(JS Fiddle 显示问题:http://jsfiddle.net/davetropeano/58vm9r6g/7/

【问题讨论】:

  • data-bind="click: $component.delete.bind($component)" 应该可以工作。现在你只是将一个函数传递给点击绑定。它不知道该函数来自哪里,这意味着它无法使用正确的上下文调用它。 data-bind="click: function () { $component.delete($data) }" 也可以工作,因为您在 on 为它提供正确上下文的视图模型上调用删除函数。
  • 使用 self 来完全避免处理调用上下文的需要也是 Luis 回答的一个选项。

标签: knockout.js knockout-components


【解决方案1】:

由于某种原因,remove 方法中的“this”没有引用 KVPairList。

这就是为什么我通常建议使用作用域变量来引用实例并防止这种关闭问题:

试试这个:

function KVPairList(params) {
    var self = this;

    self.add = function(){
         self.items.push(new KV(this.k(), this.v()));   
    };

    self.delete = function(item){
        self.items.remove(item);  
    }
    self.items = params.items;
    self.keyHeading = params.keyHeading || 'Key';
    self.valueHeading = params.valueHeading || 'Value';
    self.k = ko.observable();
    self.v = ko.observable();   
}

View Model 代码也变得更加独立。

在这里拉小提琴:

http://jsfiddle.net/luisvsilva/uzs7qhbs/1/

【讨论】:

  • 谢谢。我总是使用self = this 表格,但这次不管出于什么原因都没有。我发现如果你不想使用self 变量,你也可以在原型上使用.bind(this)this.delete = function() { ... }.bind(this);
  • 查看我对这个问题的评论。 'this' 不是 KVPairList 的原因很简单。
猜你喜欢
  • 2013-01-31
  • 2023-03-14
  • 2016-03-21
  • 2013-04-22
  • 2014-11-20
  • 2012-04-11
  • 2023-03-16
  • 2021-02-12
  • 1970-01-01
相关资源
最近更新 更多