gpt4 book ai didi

javascript - Knockout Ajax with Interval 仅显示更改的数据

转载 作者:行者123 更新时间:2023-11-29 16:51:04 25 4
gpt4 key购买 nike

我有这个代码:

function MyViewModel()
{
var myviewmodel=this;
myviewmodel.ajaxData=ko.observableArray([]);


myviewmodel.init=function()
{
updateInterval(function()
{
myviewmodel.getData();
},6000);
}

myviewmodel.getData=function()
{
myviewmodel.ajaxData([])
$.get('getData.php')
.done(function(data)
{
if(data.status==='ok' && data.data)
{
$.map(data.data,function(f)
{
var last_item=new AjaxItem(f);
myviewmodel.ajaxData.push(last_item);
})
}
})
}

function AjaxItem(data)
{
var item=this;
item.id=parseInt(data.id);
item.name=ko.observable(data.name);
item.surname=ko.observable(data.surname);
item.viewed=ko.observable(true);

setTimeout(function()
{
item.viewed(false);
},600);
}
}
var vm= new MyViewModel();
ko.applyBindings(vm)
vm.init();

我在这个 html 中查看它

<!doctype html>
<html>
<head>
........
<script src="somejs.js"></script>

<style>
.green{
background-color:green;
}
</style>
</head>
<body>
<table>
<tbody data-bind="foreach:ajaxData">
<tr data-bind="css{'green:viewed'}">
<td data-bind="text:name"></td><td data-bind="text:surname"></td>
</tr>
</tbody>
</table>
</boby>
</html>

问题是,当我进行调用时,我必须重新填充数组 ajaxData 并且当我这样做时会出现某种“闪烁”,我想要的是找到任何已更改的项目并仅显示它们。

有3种不同情况:

  1. Id 存在,但名字和姓氏不同,那么我想更改名字和姓氏。
  2. 存在于 Javascript 中的项目不存在于调用返回的数据中,因此我想从 ajaxData 中删除
  3. 返回的数据中不存在该项目,因此我想将其添加到 ajaxData 可观察数组的末尾。

你们知道怎么做吗?

注意:问题在于如何进行比较。我如何知道已返回的数据中是否存在一个返回值。

最佳答案

你的三个要求正是Knockout Mapping Plugin会为你做的。

但在此之前,您的一般方法中有几件事需要解决。

首先,让我们从 View 模型中取出 Ajax 内容。一个将所有 API 调用收集在一个地方并将它们公开为函数的对象怎么样?

这公开了 .getData()(它又在内部使用了 .get())。

var API = {
get: function (url, params) {
return $.get(url, params, null, "json").then(function (result) {
if (result.status === 'ok') return result;
console.error("Error status for " + url + ": " + result.status, result);
}).fail(function (jqXhr, status, error) {
console.error("Could not get " + url + ", error is: " + error);
});
},
getData: function(params) {
return this.get('getData.php', params);
}
};

接下来,不要将您的 View 模型称为“Viewmodel”。那是他们的目的,不应该是他们的名字。您似乎在这里有两种类型的东西,项目和项目列表。我不知道你的项目实际上是什么,所以我坚持使用名称Item,你可以选择一个更好的。因此,让我们创建两个构造函数:

function Item(data) {
var self = this;
self.id = parseInt(data.id);
self.name = ko.observable(data.name);
self.surname = ko.observable(data.surname);
self.viewed = ko.observable(true);
setTimeout(function () {
self.viewed(false);
}, 600);
}

function ItemList() {
var self = this;
self.data = ko.observableArray();

self.init = function (data) {
ko.mapping.fromJS(data, ItemList.mapping, self);
};
self.load = function () {
API.getData().done(self.init);
};
}

请注意 API 的调用方式,这使得 ItemList View 模型更易于阅读。另请注意,将 loadinit 分开如何使您能够使用未通过 Ajax(可能是 localStorage?)获取的数据初始化 View 模型。

您可以在此处看到我们如何调用 ko.mapping.fromJS。为了将传入对象映射到功能 View 模型中, View 模型属性应该像数据属性一样被调用。

假设您的 Ajax 响应如下所示:

{
status: "ok",
data: [
{id: 1, name: "Doctor", surname: "Evil"},
{id: 2, name: "Austin", surname: "Powers"}
]
}

有两个属性,statusdata

  • status 我们想忽略,它对 viewmodel 的功能并不重要。
  • data 包含一个对象列表,这些对象应该成为我们的同名可观察数组中的 Item 实例。

为此,映射插件需要说明。为方便起见,我们可以将它们放在 ItemList 对象上。

ItemList.mapping = {
ignore: ["status"],
data: {
key: function (data) {
return ko.unwrap(data.id);
},
create: function (options) {
return new Item(options.data);
}
}
};

这告诉映射插件不要理会 status,而是对 data 中的对象做两件事:

  • key 函数将用于确定对象的 ID,因此映射插件知道何时应该使用传入的对象来更新现有的 View 模型。为此,我们使用 id 属性。
  • create 函数将用于将传入的普通对象转换为 Item 实例。

现在每次 ko.mapping.fromJS 被来自服务器的新数据调用时,knockout 将挑选现有对象并只更新已更改的属性,而不是重新绘制整个列表.缺少的对象将从屏幕上删除,新的对象将被添加。


View 保持不变:

<table>
<tbody data-bind="foreach: data">
<tr data-bind="css: {green: viewed}">
<td data-bind="text: name"></td>
<td data-bind="text: surname"></td>
</tr>
</tbody>
</table>

将它们放在一起(展开并运行示例):

var API = {
get: function (url, params) {
return $.get(url, params, null, "json").then(function (result) {
if (result.status === 'ok') return result;
console.error("Error status for " + url + ": " + result.status);
}).fail(function (jqXhr, status, error) {
console.error("Could not get " + url + ", error is: " + error);
});
},
getData: function(params) {
return this.get('getData.php', params);
}
};
// -------------------------------------------------------------------

function Item(data) {
var self = this;
self.id = parseInt(data.id);
self.name = ko.observable(data.name);
self.surname = ko.observable(data.surname);
self.viewed = ko.observable(true);
setTimeout(function () {
self.viewed(false);
}, 600);
}

function ItemList() {
var self = this;
self.data = ko.observableArray();

self.init = function (data) {
ko.mapping.fromJS(data, ItemList.mapping, self);
};
self.load = function () {
API.getData().done(self.init);
};
}
ItemList.mapping = {
ignore: ["status"],
data: {
key: function (data) {
return ko.unwrap(data.id);
},
create: function (options) {
return new Item(options.data);
}
}
};
// -------------------------------------------------------------------

// Ajax mockup
$.mockjax({
url: "getData.php",
responseText: {
status: "ok",
data: [
{id: 1, name: "Doctor", surname: "Evil"},
{id: 2, name: "Austin", surname: "Powers"}
]
}
});

var vm = new ItemList();
ko.applyBindings(vm);
vm.load();
setInterval(vm.load, 6000);
.green {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.6.2/jquery.mockjax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

<table>
<tbody data-bind="foreach: data">
<tr data-bind="css: {green: viewed}">
<td data-bind="text: name"></td>
<td data-bind="text: surname"></td>
</tr>
</tbody>
</table>

<hr>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

关于javascript - Knockout Ajax with Interval 仅显示更改的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36081144/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com