knockout.js 主视图模型中的一个视图模型(添加项目变得未定义)

Posted

技术标签:

【中文标题】knockout.js 主视图模型中的一个视图模型(添加项目变得未定义)【英文标题】:knockout.js one viewmodel in main viewmodel(add item become undefined) 【发布时间】:2017-09-01 09:21:21 【问题描述】:

这是代码

<form data-bind="submit: addItem">
New item:
<input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button>
<p>Your items:</p>
<select multiple="multiple"  data-bind="options: items"> </select>

这是视图模型

    var SimpleListModel = function(items) 
    this.items = ko.observableArray(items);
    this.itemToAdd = ko.observable("");
    this.addItem = function() 
        if (this.itemToAdd() != "") 
            this.items.push(this.itemToAdd()); // Adds the item. Writing to the "items" observableArray causes any associated UI to update.
            this.itemToAdd(""); // Clears the text box, because it's bound to the "itemToAdd" observable
        
    .bind(this);  // Ensure that "this" is always this view model
;

var masterVM = (function () 
         var self = this;      
         self.SimpleListModel= new SimpleListModel(["Alpha", "Beta", "Gamma"]);

)();
ko.applyBindings(masterVM); 

我的页面上必须有多个视图模型。因此,对于初学者,我创建了一个视图模型并将其放入一个主视图模型中。但 addItem 变得未定义。为什么会这样?我怎样才能让这种方法奏效?

编辑

  <div data-bind="with: viewModel2">
       <div>
           <span data-bind="text: boardtext" />                          
       </div>           
       <a href="#" id="addVar" data-bind="click: addList ,visible: sh">Add a List</a><br /><br />
       <form method="post">           
        <div data-bind="foreach: lists" id="thumbnails">             
           <div class="thumbnail-container">
               <span data-bind="text:listname"></span><br /><br /><br /><br />
               <div id="abc">
                   <ul class="list-group" data-bind="foreach: cardlists">
                       <li class="list-group-item">
                           <span data-bind="text: cardname"></span>
                           <a href="#" data-bind="click: $root.removecard">Del</a>
                       </li>
                   </ul>
                   <a href="#" data-bind="click:  $parent.showhideaddcard,visible: cardvisiblity">Add Card</a><br />
                   <div data-bind="visible: showRenderTimes">
                       <input type="text" data-bind="value: $parent.cardtext" /><br /><br /><br />
                       <input type="button" value="Add" data-bind="click: $parent.addcard" />
                       <input type="button" value="Cancel" data-bind="click: $parent.cancelcard" />
                   </div>
                   <div data-bind="visible: showlist">
                       <input type="text" data-bind="value: $parent.listtext" /><br /><br />
                       <input type="button" value="Save list" data-bind="click: $parent.addbuttonlist" />
                   </div>
               </div>
           </div>
       </div>

       <p class="alignRight">
           <input type="submit" value="Update">
       </p>
   </form>
 </div>

【问题讨论】:

你把那些html包裹在with: SimpleListModel里面了吗? 我只是将一个 with:SimpleListModel 包装在了一个 div 中 它不起作用 对不起,它有效 【参考方案1】:

您需要使用with: ... 包装表单。这是示例。

var SimpleListModel = function(items) 
  this.items = ko.observableArray(items);
  this.itemToAdd = ko.observable("");
  this.addItem = function() 
    console.log("trigger AddItem");
  .bind(this);  // Ensure that "this" is always this view model
;

var masterVM = (function () 
  var self = this;      
  self.SimpleListModel= new SimpleListModel(["Alpha", "Beta", "Gamma"]);      
)();

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

<div data-bind="with: SimpleListModel">
  <form data-bind="submit: addItem">
    New item:
    <input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' />
    <button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button>
    <p>Your items:</p>
    <select multiple="multiple"  data-bind="options: items"></select>
  </form>
</div>

【讨论】:

绝对是比我更干净的解决方案,不知道'with'绑定,很棒的东西。【参考方案2】:

问题在于 SimpleListModel 是绑定到页面的 masterVM 的属性,这意味着您必须在 HTML 中使用 SimpleListModel 作为所有可观察绑定的前缀,如下所示:

<form data-bind="submit: SimpleListModel.addItem">
New item:
<input data-bind='value: SimpleListModel.itemToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: SimpleListModel.itemToAdd().length > 0">Add</button>
<p>Your items:</p>
<select multiple="multiple"  data-bind="options: SimpleListModel.items"> </select>

jsfiddle:https://jsfiddle.net/me7Lj5r1/

【讨论】:

$root.remove 函数呢?这以前在我的代码中有效。我这里没有展示。 差不多,或者替代方法是在使用 SimpleListModel 属性的 html 周围包裹的 div 中使用上面提到的 with 绑定。如果您不需要 masterVM 并且只是将 SimpleListModel 绑定到页面,那么一切都可以正常工作,但是按照您现在的方式进行操作会更方便,因为这意味着您本质上可以拥有多个视图模型。 如何在数据绑定中插入视图模型:$root.removefunction $root.removefunction 是 masterVM 的一部分还是 SimpleListModel 的一部分? SimpleListModel

以上是关于knockout.js 主视图模型中的一个视图模型(添加项目变得未定义)的主要内容,如果未能解决你的问题,请参考以下文章

在 knockout.js 中将 observable 从一个视图模型传递到另一个视图模型

Knockout.js - 封装视图模型并从外部隐藏它们

在 knockout.js 视图模型(数组)中存储特定元素

多视图模型破坏了 knockout.js

在 knockout.js 视图模型中使用 `var self = this` 有啥好处 [重复]

模型更改时视图中的列表不会更新