模型更改时视图中的列表不会更新
Posted
技术标签:
【中文标题】模型更改时视图中的列表不会更新【英文标题】:list in View does not update when the Model changes 【发布时间】:2018-03-31 12:19:55 【问题描述】:我正在尝试使用 knockout.js 构建 MVVM。这个想法是 $(document).ready(function() ... 中的脚本添加了一个新项目 model.addElement("value"); -每 3 秒向模型添加一次“值”,并且应该以 html 格式显示。尽管在控制台输出中您可以看到模型正在更改并且元素被推送到 items 列表,但 HTML 保持不变。
同时,如果我取消注释 self.items.push($('#new_item').val()); 行 - 每次添加元素时 HTML 页面都会发生变化到模型。
请帮助我理解我做错了什么,为什么我不能通过 model.addElement("value"); 行传递这个“值”字符串?
// 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>
统一更新: 也许我说不清楚,我想要的是每 3 秒向模型添加一次新值,并且此更改显示在视图 (HTML) 中。 正如@user3297291 所建议的那样,我实现了将 self.items().push(item); 更改为 self.items.push(item);。 这是代码的最终版本,完全符合我的要求:
// 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);
);
<!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>
【问题讨论】:
【参考方案1】:一些使您的 sn-p 正常工作的小错误修复:
不要推送到数组insideself.items
,因为敲除将无法注意到它的内容发生了变化。直接推送到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("")
清除它
使用淘汰赛时,您将规则设置为不以任何其他方式接触 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>
【讨论】:
请问你这个“显示代码sn-p”是怎么做到的? 编辑 sn-p 时,左侧有一个“默认隐藏 sn-p”复选框,您可以勾选。此复选框设置也包含在您帖子中插入的标记标题中:hide: true
(默认值为false
)以上是关于模型更改时视图中的列表不会更新的主要内容,如果未能解决你的问题,请参考以下文章
数据库更改时,Android SimpleCursorAdapter 不会更新
当视图模型@Published 更改时,SwiftUI 列表因“NSRangeException”而崩溃