【问题标题】:knockout js cannot delete after adding to observable array淘汰js添加到可观察数组后无法删除
【发布时间】:2017-03-05 23:45:41
【问题描述】:

我正在尝试使用 Knockout js 完成一些基本的添加和删除功能。

我正在使用 asp mvc,淘汰映射插件并返回一个简单的字符串列表作为我的 viewModel 的一部分

目前我从服务器获得三个项目,我创建的功能允许我删除这些项目中的每一个。我还可以添加一个项目。但是,如果我尝试删除我在 KO 脚本中添加的项目,我将无法删除它。

在完成研究和一些测试后,我想我错误地使用了 observable。我更改了我的代码以通过ko.observable(""),但这并没有奏效。我做错了什么?

加载值

数组[4]0:“测试1”1:“测试2”2:“测试3”长度:4__proto__:数组[0]

点击添加后的值

数组[4]0:“测试1”1:“测试2”2:“测试3”3:c()长度:4__proto__:数组[0]

ko 脚本

    var vm = function (data) {
        var self = this;

        ko.mapping.fromJS(data, {}, self);

        this.deleteBulletPoint = function (bulletPoint) {
            self.BulletPoints.remove(bulletPoint)
        }

        this.addEmptyBulletPoint = function () {
            self.BulletPoints.push(ko.observable(""));
            console.log(self.BulletPoints())
        }
    }

HTML

<div class="col-lg-6 col-md-6 col-sm-12">
    <h4>Bullet Points</h4>
    <div id="oneLinedescriptions" class="input_fields_wrap">
        <!-- ko foreach: BulletPoints -->
        <div class="form-group">
            <div class="input-group">
                <input type="text" data-bind="value: $data" class="form-control">
                <span data-bind="click: $parent.deleteBulletPoint" class="input-group-addon btn">-</span>
            </div>
        </div>
        <!-- /ko -->
    </div>
    <button id="btnAddDescription" data-bind="click: addEmptyBulletPoint" type="button" class="btn btn-default add_field_button col-lg-12 animate-off">Add New Bullet Point</button>
</div>

编辑

我已删除$parent,但返回以下错误

未捕获的 ReferenceError: 无法处理绑定“foreach: function (){return BulletPoints }” 消息:无法处理绑定“点击:函数(){return deleteBulletPoint}” 消息:deleteBulletPoint 未定义

除此之外,我还能够添加新的空元素,但是当用户更改值时它们不会更新。这是因为我添加的元素是不可观察的吗?如果是这样,我该如何绕过它?

【问题讨论】:

  • “他们没有更新”到底是什么意思?哪个字段没有更新,BulletPoints 数组中的字符串值?您在哪里定义 BulletPoints,是 observableArray 还是普通数组?你能显示那个代码吗?

标签: javascript knockout.js


【解决方案1】:

我添加了一个 sn-p 来说明如何使用带有 Knockout 的 Observable 数组添加和删除,大部分代码都是直接来自你的,所以你在正确的轨道上。

请注意,在绑定到方法时,在这种情况下,不需要引用 $parent,因为您没有使用嵌套范围。此外,在添加时,您只需传入 纯文本,因为 observableArray 需要一个对象。

如果您使用更复杂的类型,则在添加时需要传递对象本身,并在迭代器范围内从中引用其属性,您可以阅读更多关于它的信息here

希望这会有所帮助。

var vm = function (data) {
    var self = this;
    
    this.BulletPoints = ko.observableArray(["test1", "test2", "test3"]);

    this.deleteBulletPoint = function (bulletPoint) {
        self.BulletPoints.remove(bulletPoint)
    }

    this.addEmptyBulletPoint = function () {
        const c = self.BulletPoints().length + 1;
        self.BulletPoints.push("test "+c);
    }
}

ko.applyBindings(vm);

        
a {
  cursor: pointer;
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<h4>Bullet Points <span><a data-bind="click: addEmptyBulletPoint">Add +</a></span></h4>
<div data-bind="foreach: BulletPoints">
   <div class="input-group">
      <h3 data-bind="text: $data"></h3>
      <a data-bind="click: deleteBulletPoint">Delete</a>
  </div>
<div>

【讨论】:

  • 澄清一点:OP 的情况可能需要“$parent”(对于删除功能),因为他使用的是“foreach”子上下文。在上面的 sn-p 中,它在没有 $parent 引用的情况下工作的原因实际上是因为使用“vm”而不是“new vm()”错误地执行了 applyBindings 调用,并且添加/删除方法正在做一些奇怪的事情,比如被添加全局到窗口对象。
  • 我会修改的!感谢您的反馈。
  • 感谢您的回答。正如@Jason 所说,我需要 $parent 。请查看我的编辑,因为我的值仍然是空字符串
  • 正确,因为您的代码使用内联 &lt;! -- ko foreach:...&gt;,这会创建一个内部上下文,要求您通过 $parent 访问父范围组件。在我的示例中,我通过 html data-bind 属性使用了foreach,它不会创建子范围。我发现这是一种更清洁的方法。你试过用那个吗?
【解决方案2】:

您遇到的问题与 ko.mapping 处理原始类型数组的方式有关。按照设计,只有作为对象一部分的属性才会映射到可观察对象,因此字符串数组将成为字符串的 observableArray。它将不会变成 observable 字符串的 observableArray。

为了在项目本身可观察的数组中添加/删除项目,您必须使 BulletPoints 数组成为一个对象数组,其中包含字符串作为属性:

data = { BulletPoints: [{value: "test1"}, {value: "test2"}] }

这是一个工作示例:jsfiddle

【讨论】:

    猜你喜欢
    • 2014-05-18
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 2013-06-02
    • 2015-07-14
    • 2015-03-20
    • 2012-10-14
    相关资源
    最近更新 更多