我正在尝试使用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;
UPD: 也许我已经弄清楚了,我想要的是每3秒将新值添加到模型中并且此更改显示在视图(HTML)上。 我实现了将 self.items()。push(item); 更改为 self.items.push(item); ,正如@ user3297291建议的那样。 这是代码的最终版本,它完全符合我的要求:
// 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;
答案 0 :(得分:1)
使您的代码段有效的一些小错误修复:
self.items
内的数组,因为knockout将无法注意到其内容已更改。直接推送至observableArray
:self.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>