模型更改时,View中的列表不会更新

时间:2017-10-19 12:48:23

标签: javascript jquery html mvvm knockout.js

我正在尝试使用knockout.js构建MVVM。我们的想法是 $(document).ready(function(){...} 中的脚本添加了一个新项 model.addElement(" value"); - "值"每隔3秒对模型进行一次,并且应该以HTML格式显示。尽管在控制台输出中你可以看到模型正在改变,元素被推送到项目 list,HTML保持不变。

同时,如果我取消注释 self.items.push($(' #new_item')。val()); 行 - HTML页面将每次更改元素添加到模型的时间。

请帮助我理解我做错了什么,为什么我不能通过这个"价值"字符串通过 model.addElement("值"); 行?



// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function(item) {
  var self = this;
  self.item = item;

  self.items = ko.observableArray(["First", "Second", "Third"]);

  self.addElement = function(item) {
    self.items().push(item);
    //self.items.push($('#new_item').val()); //--> uncomment for adding element with a button click
  }

};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));

$(document).ready(function() {
  //comment this if you want add elements only when you click on button
  setInterval(function() {
    model.addElement("value");
    console.log(model.items());
  }, 3000);
});

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <title>Updating list to the server (automatically)</title>

</head>

<body>
  <div id="one">
    <h1>Records:</h1>

    <div class="list-group" data-bind="foreach: items">
      <a href="#" class="list-group-item" data-bind="text: $data"></a>
    </div>

    <div class="form-group">
      <label for="new_item">Item name:</label>
      <input type="text" class="form-control" id="new_item">
    </div>

    <form>
      <input type="button" class="btn btn-info" value="Add element" data-bind="click: addElement">
    </form>
  </div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>

</html>
&#13;
&#13;
&#13;

UPD: 也许我已经弄清楚了,我想要的是每3秒将新值添加到模型中并且此更改显示在视图(HTML)上。 我实现了将 self.items()。push(item); 更改为 self.items.push(item); ,正如@ user3297291建议的那样。 这是代码的最终版本,它完全符合我的要求:

&#13;
&#13;
// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function() {
  var self = this;

  self.items = ko.observableArray(["First", "Second", "Third"]);
  //self.item = ko.observable("");

  self.addElement = function(item) {
    self.items.push(item);
  }

};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));

$(document).ready(function() {
  //comment this if you want add elements only when you click on button
  setInterval(function() {
    model.addElement("value");
    console.log(model.items());
  }, 3000);
});
&#13;
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <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.4.2/knockout-min.js"></script>

  <title>Updating list to the server (automatically)</title>


</head>

<body>
  <div id="one">
    <h1>Records:</h1>

    <div class="list-group" data-bind="foreach: items">
      <a href="#" class="list-group-item" data-bind="text: $data"></a>
    </div>
  </div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

使您的代码段有效的一些小错误修复:

  • 不要推送到 self.items内的数组,因为knockout将无法注意到其内容已更改。直接推送至observableArrayself.items.push代替self.items().push
  • 使self.item可观察,以便您可以将其值绑定到文字输入:self.item = ko.observable("")
  • 使用value绑定同步self.item<input/>.value<input data-bind="value: item">
  • addElement没有收到项目,它接收事件和当前绑定上下文。相反,您可以使用self.item()检索文本框'值,推送它,然后使用self.item("")
  • 清除它

使用knockout时,除了通过敲除绑定之外,您将规则设置为不以任何其他方式触摸DOM。无论何时使用jQuery设置或检索值,您应该问的第一个问题是“我可以使用什么样的敲除绑定”。

固定版本:

// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function(item) {
  var self = this;
  self.item = ko.observable("");

  self.items = ko.observableArray(["First", "Second", "Third"]);

  self.addElement = function() {
    self.items.push(self.item());
    self.item("");
  }

};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <title>Updating list to the server (automatically)</title>

</head>

<body>
  <div id="one">
    <h1>Records:</h1>

    <div class="list-group" data-bind="foreach: items">
      <a href="#" class="list-group-item" data-bind="text: $data"></a>
    </div>

    <div class="form-group">
      <label for="new_item">Item name:</label>
      <input type="text" class="form-control" id="new_item" data-bind="value: item">
    </div>

    <form>
      <input type="button" class="btn btn-info" value="Add element" data-bind="click: addElement">
    </form>
  </div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>

</html>