2013-04-24 60 views
1

我正在學習KO並嘗試創建一個簡單的列表項添加/刪除。但我有以下問題。 Q1:如果您單擊添加而不輸入名稱,則您剛剛添加的項目將具有result作爲名稱。爲什麼以及如何防止它,同時允許空作爲有效的輸入?問題2:我想用<pre>標籤來顯示當前視圖模型的JSON,但它沒有顯示任何內容。但按鈕顯示的東西。 我想出了這一個。我需要使用ko.toJSON($data, null, 4)綁定和ko.toJSON不按預期工作

Q3:它與Q2相關,按鈕顯示某些內容,但它顯示的內容似乎很奇怪。輸入幾個項目後,點擊debug按鈕。您會看到視圖模型中的所有項目都被您更改的最後一個項目替換。

這是fiddle

CSS:

input[type=text], select { 
    width:100px; 
} 

JS:

function foodie() { 
    this.name; 
    this.food; 
} 

function foodieApp() { 
    var self = this; 
    self.foodies = ko.observableArray(); 
    self.foodieToAdd = ko.observable(new foodie()); 

    self.addFoodie = function() { 
     this.foodies.push(this.foodieToAdd()); 
    }; 

    self.delFoodie = function (foodieToDel) { 
     self.foodies.remove(foodieToDel); 
    }; 

    self.debug = function() { 
     alert(ko.toJSON(self, null, 4)); 
    }; 
} 

var app = new foodieApp(); 
ko.applyBindings(app); 

HTML:

<table> 
    <thead> 
     <tr> 
      <td>Foodie's Name 
       <br/> 
       <input type=text data-bind='value: foodieToAdd().name' /> 
      </td> 
      <td>Foodie's Food 
       <br/> 
       <select data-bind='value: foodieToAdd().food'> 
        <option value=apple>Apple</option> 
        <option value=banana>Banana</option> 
        <option value=cherry>Cherry</option> 
       </select> 
      </td> 
      <td> 
       <input type=button value=Add data-bind='click: addFoodie' /> 
      </td> 
     </tr> 
    </thead> 
    <tbody data-bind='foreach: foodies'> 
     <tr> 
      <td> 
       <input type=text data-bind='value: name' /> 
      </td> 
      <td> 
       <select data-bind='value: food'> 
        <option value=apple data-bind>Apple</option> 
        <option value=banana>Banana</option> 
        <option value=cherry>Cherry</option> 
       </select> 
      </td> 
      <td> 
       <input type=button value=del data-bind='click: $parent.delFoodie' /> 
      </td> 
     </tr> 
    </tbody> 
</table> 
<input type=button value=debug data-bind='click: debug' /> 
<!-- why the following <pre> tag is empty? --> 
<pre data-bind='text: ko.toJSON(app, null, 4)'></pre> 

回答

2

這裏是一個更新的小提琴:http://jsfiddle.net/jearles/TgD6a/3/

-

  • Q1:你沒有初始化你foodie對象
  • Q2:app是不是你的視圖模型的一部分 - 它是視圖模型。使用$root訪問頂級ViewModel問題3:這與您定義方式foodieToAdd的方式有關。基本上你只能創建一個實例,所以Knockout一直添加同一個對象。因爲您沒有可觀察的屬性,所以敲除沒有更新UI。

在我的小提琴中,我改變了如何定義foodieToAdd。它現在只是一個標準對象,具有兩個可觀察的屬性。當您單擊add時,它會克隆foodieToAdd以在observableArray中創建一個新條目。

編輯:見下面的評論爲什麼淘汰賽是拾起result

-

function foodie(foodie) { 
    this.name = ko.observable(foodie ? foodie.name() : ''); 
    this.food = ko.observable(foodie ? foodie.food() : ''); 
} 

function foodieApp() { 
    var self = this; 
    self.foodies = ko.observableArray(); 
    self.foodieToAdd = new foodie(); 

    self.addFoodie = function() { 
     this.foodies.push(new foodie(this.foodieToAdd)); 
    }; 

    self.delFoodie = function (foodieToDel) { 
     self.foodies.remove(foodieToDel); 
    }; 

    self.debug = function() { 
     alert(ko.toJSON(self, null, 4)); 
    }; 
} 

var app = new foodieApp(); 
ko.applyBindings(app); 
+0

這是正確的,但我不明白,爲什麼'result'是越來越放在'name'結合。有任何想法嗎? – 2013-04-24 23:07:06

+0

我不完全是爲什麼,除了它必須綁定到屬性沒有初始化。它看起來像是Knockout的DOM渲染邏輯中的一些東西。如果你看這個小提琴(http://jsfiddle.net/jearles/TgD6a/4/),你會看到你的調試渲染。你會在對象中看不到任何名字,但是你可以把'result'改成'res',如果你點擊add,它就會獲得這個值。 – 2013-04-24 23:25:58

+0

今天早上我做了一些調試,交換了knockout的調試版本。 「結果」的原因正在變得非常簡單,但它涉及到一點JavaScript語句:'with'。 淘汰賽正在評估此功能: '用($上下文){用($數據|| {}){{回報 '值':姓名,...}}}' 的'with'語句添加'$ context'和'data'到它將嘗試解析'name'的範圍鏈。這兩者都沒有'name'屬性,但'this'(這是Window)確實......並且它是'result'。嘗試將'name'改爲'foodieName',我們不再有意想不到的'結果'。 – 2013-04-25 11:42:13