如果启用了无限滚动,如何防止剑道网格两次加载数据?
Posted
技术标签:
【中文标题】如果启用了无限滚动,如何防止剑道网格两次加载数据?【英文标题】:How to prevent the Kendo grid from loading the data twice if endless scrolling is enabled? 【发布时间】:2020-04-27 06:54:28 【问题描述】:我有一个带有服务器端分页/排序/过滤和无限滚动功能的剑道网格。在这种情况下,我遇到的问题是,当网格被过滤时,数据被加载了两次。第一次加载所有数据,第二次加载过滤后的数据。
要重现问题,您必须执行以下步骤。
代码示例:https://dojo.telerik.com/@Ruben/OnODErav
-
在网格中向下滚动,直到加载新数据
现在控制台中应该有两次“Grid data bound”事件
在任何列上设置任何过滤器
现在您在控制台中有四次“绑定网格数据”事件,而不是三次!
只有在您向下滚动后才会出现该错误。如果您重新启动并且只执行第三步,您将看到该事件仅被触发了两次(第一次和过滤后),这是正确的。
有人知道如何防止它两次加载数据吗?
function onDataBound(arg)
kendoConsole.log("Grid data bound");
$(document).ready(function()
$("#grid").kendoGrid(
dataSource:
type: "odata",
transport:
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
,
schema:
model:
fields:
OrderID: type: "number" ,
Freight: type: "number" ,
ShipName: type: "string" ,
OrderDate: type: "date" ,
ShipCity: type: "string"
,
pageSize: 20,
serverPaging: true,
serverFiltering: true,
serverSorting: true
,
height: 550,
dataBound: onDataBound,
filterable: true,
sortable: true,
scrollable:
endless: true
,
pageable:
numeric: false,
previousNext: false
,
columns: [
field:"OrderID",
filterable: false
,
"Freight",
field: "OrderDate",
title: "Order Date",
format: "0:MM/dd/yyyy"
,
field: "ShipName",
title: "Ship Name"
,
field: "ShipCity",
title: "Ship City"
]
);
);
(function($, undefined)
window.kendoConsole =
log: function(message, isError, container)
var lastContainer = $(".console div:first", container),
counter = lastContainer.find(".count").detach(),
lastMessage = lastContainer.text(),
count = 1 * (counter.text() || 1);
lastContainer.append(counter);
if (!lastContainer.length || message !== lastMessage)
$("<div" + (isError ? " class='error'" : "") + "/>")
.css(
marginTop: -24,
backgroundColor: isError ? "#ffbbbb" : "#b2ebf2"
)
.html(message)
.prependTo($(".console", container))
.animate( marginTop: 0 , 300)
.animate( backgroundColor: isError ? "#ffdddd" : "#ffffff" , 800);
else
count++;
if (counter.length)
counter.html(count);
else
lastContainer.html(lastMessage)
.append("<span class='count'>" + count + "</span>");
,
error: function(message)
this.log(message, true);
;
)(jQuery);
/*
* jQuery Color Animations
* Copyright 2007 John Resig
* Released under the MIT and GPL licenses.
*/
(function(jQuery)
// We override the animation for all of these color styles
jQuery.each(["backgroundColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "outlineColor"], function(i, attr)
jQuery.fx.step[attr] = function(fx)
if (!fx.state || typeof fx.end == typeof "")
fx.start = getColor(fx.elem, attr);
fx.end = getRGB(fx.end);
fx.elem.style[attr] = ["rgb(", [
Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0),
Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0),
Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0)
].join(","), ")"].join("");
;
);
// Color Conversion functions from highlightFade
// By Blair Mitchelmore
// http://jquery.offput.ca/highlightFade/
// Parse strings looking for color tuples [255,255,255]
function getRGB(color)
var result;
// Check if we're already dealing with an array of colors
if (color && color.constructor == Array && color.length == 3)
return color;
// Look for rgb(num,num,num)
result = /rgb\(\s*([0-9]1,3)\s*,\s*([0-9]1,3)\s*,\s*([0-9]1,3)\s*\)/.exec(color);
if (result)
return [parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)];
// Look for #a0b1c2
result = /#([a-fA-F0-9]2)([a-fA-F0-9]2)([a-fA-F0-9]2)/.exec(color);
if (result)
return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)];
// Otherwise, we're most likely dealing with a named color
return jQuery.trim(color).toLowerCase();
function getColor(elem, attr)
var color;
do
color = jQuery.css(elem, attr);
// Keep going until we find an element that has color, or we hit the body
if (color && color != "transparent" || jQuery.nodeName(elem, "body"))
break;
attr = "backgroundColor";
elem = elem.parentNode;
while (elem);
return getRGB(color);
var href = window.location.href;
if (href.indexOf("culture") > -1)
$("#culture").val(href.replace(/(.*)culture=([^&]*)/, "$2"));
function onlocalizationchange()
var value = $(this).val();
var href = window.location.href;
if (href.indexOf("culture") > -1)
href = href.replace(/culture=([^&]*)/, "culture=" + value);
else
href += href.indexOf("?") > -1 ? "&culture=" + value : "?culture=" + value;
window.location.href = href;
$("#culture").change(onlocalizationchange);
)(jQuery);
/*global*/
.floatWrap:after,#example:aftercontent:"";display:block;clear:both
.floatWrap,#exampledisplay:inline-block
.floatWrap,#exampledisplay:block
.clearclear:both
body,h1,h2,h3,h4,p,ul,li,a,button
margin:0;
padding:0;
list-style:none;
html
top: 0;
left: 0;
overflow-y:scroll;
font:75% Arial, Helvetica, sans-serif;
background: #f5f7f8;
body
margin: 0;
padding: 0;
a,
li>a,
h2>a,
h3>a,
a
text-decoration:none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
a
color: #0487c4;
a:hover
text-decoration: underline;
.page
max-width:72%;
margin: 2% auto;
padding: 3% 5% 0;
background: #fff;
border: 1px solid #e2e4e7;
.offline-button
display: inline-block;
margin: 0 0 30px;
padding: 9px 23px;
background-color: #015991;
border-radius: 2px;
color: #fff;
text-decoration: none;
font-size: 13px;
font-weight: 700;
line-height: 1.2;
transition-duration: 0.2s;
transition-property: background-color;
transition-timing-function: ease;
.offline-button:hover
background-color: #013a5e;
color: #fff;
text-decoration: none;
#example
margin: 2em 0 5em;
padding: 0;
border: 0;
background: transparent;
font-size: 14px;
/*console*/
.console
background-color: transparent;
color: #333;
font: 11px Consolas, Monaco, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
margin: 0;
overflow-x: hidden;
text-align: left;
height: 200px;
border: 1px solid rgba(20,53,80,0.1);
background-color: #ffffff;
text-indent: 0;
.demo-section .box-col .console
min-width: 200px;
.console .count
background-color: #26c6da;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
color: #ffffff;
font-size: 10px;
margin-left: 5px;
padding: 2px 6px 2px 5px;
.console div
background-position: 6px -95px;
border-bottom: 1px solid #DDD;
padding: 5px 10px;
height: 2em;
line-height: 2em;
vertical-align: middle;
.console .error
background-position: 6px -135px;
/*configurator*/
.centerWrap .configuration,
.configuration,
.configuration-horizontal
margin: 4.5em auto;
padding: 3em;
background-color: rgba(20,53,80,0.038);
border: 1px solid rgba(20,53,80,0.05);
.absConf .configuration
position: absolute;
top: -1px;
right: -1px;
height: auto;
margin: 0;
z-index: 2;
.configuration-horizontal
position: static;
height: auto;
min-height: 0;
margin: 0 auto;
zoom: 1;
.configuration-horizontal-bottom
margin: 20px -21px -21px;
position: static;
height: auto;
min-height: 0;
width: auto;
float:none;
.configuration .configHead,
.configuration .infoHead,
.configuration-horizontal .configHead,
.configuration-horizontal .infoHead
display: block;
margin-bottom: 1em;
font-size: 12px;
line-height: 1em;
font-weight: bold;
text-transform: uppercase;
.configuration .configTitle,
.configuration-horizontal .configTitle
font-size: 12px;
display: block;
line-height: 22px;
.configuration .options,
.configuration-horizontal .options
list-style:none;
margin: 0;
padding: 0;
.configuration button,
.configuration-horizontal button
margin: 0;
vertical-align: middle;
.configuration .k-textbox,
.configuration-horizontal .k-textbox
margin-left: 7px;
width: 30px;
.configuration .options li display: block; margin: 0; padding: 0.2em 0; zoom: 1;
.configuration .options li:after,
.configuration-horizontal:after
content: "";
display: block;
clear: both;
height: 0;
.configuration-horizontal .config-section
display: block;
float: left;
min-width: 200px;
margin: 0;
padding: 10px 20px 10px 10px;
.configuration label,
.configuration input
vertical-align: middle;
line-height: 20px;
margin-top: 0;
.configuration label
float: left;
.configuration input
width: 40px;
.configuration input,
.configuration select,
.configuration .k-numerictextbox
float: right;
.configuration input.k-input
float: none;
.configuration .k-button,
.configuration .k-widget
margin-bottom: 3px;
/* Code Viewer */
.source
background-color: #f5f7f8;
margin: 0 0 5em;
border: 1px solid rgba(20,53,80,0.05);
.source .code
background-color: #fff;
border-top: 1px solid rgba(20,53,80,0.08);
padding: 20px 0 0;
.source .code pre
margin: 0;
padding: 0 20px 20px;
.source .offline-button
background: none;
text-decoration: none;
color: #0487c4;
margin: 10px 0 10px 14px;
padding: 10px;
.source .offline-button.selected
color: #000;
.source .code .controller
display: none;
/* Pretty Print */
.prettyprint
font-size: 12px;
overflow: auto;
pre .nocode background-color: transparent; color: #000;
pre .str, /* string */
pre .atv color: #2db245; /* attribute value */
pre .kwd color: #ff3399; /* keyword */
pre .com color: #9933cc; /* comment */
pre .typ color: #000; /* type */
pre .lit color: #0099ff; /* literal */
pre .pun color: #333; /* punctuation */
pre .pln color: #3e526b; /* plaintext */
pre .tag color: #3e526b; /* html/xml tag */
pre .atn color: #3e526b; /* attribute name */
pre .dec color: #3e526b; /* decimal */
/* Specify class=linenums on a pre to get line numbering */
ol.linenums margin-top: 0; margin-bottom: 0; color: #333;
li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 list-style-type: none
li.L1,li.L3,li.L5,li.L7,li.L9 background: #eee;
/*keyboard navigation legend */
.key-button
display: inline-block;
text-decoration: none;
color: #555;
min-width: 20px;
margin: 0;
padding: 3px 5px;
font-size: 12px;
text-align: center;
border-radius: 2px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
background: #eee;
box-shadow: 0 1px 0 1px rgba(0,0,0,0.1), 0 2px 0 rgba(0,0,0,0.1);
.widest
.wider
.wide
.leftAlign, .rightAlign, .centerAlign text-align: left;
.letter
padding-top: 14px;
padding-bottom: 11px;
font-weight: bold;
font-size: 17px;
ul.keyboard-legend
list-style-type: none;
margin: 0 auto;
padding: 0;
text-align: left;
#example ul.keyboard-legend li,
.demo-section .box-col ul.keyboard-legend li
display: block;
margin: 0;
padding: 4px 0;
line-height: 1.5em;
ul.keyboard-legend li a
color: #0487C4;
.button-preview
display: inline-block;
vertical-align: top;
padding: 0 5px 0 0;
.button-descr
display: inline-block;
vertical-align: top;
text-align: left;
padding: 3px 0;
.demo-section p a.hyperlink,
.config-section a
color: #e15613;
text-decoration: none;
.chart-wrapper,
.map-wrapper,
.diagram-wrapper
position: relative;
height: 430px;
margin: 0 auto 15px auto;
padding: 10px;
#example.absConf .chart-wrapper,
#example.absConf .map-wrapper,
#example.absConf .diagram-wrapper
margin-left: 0;
.chart-wrapper .k-chart,
.map-wrapper .k-map,
.diagram-wrapper .k-diagram
height: 430px;
.config-section.console-section
width: 400px;
float: right;
#page > h2
float: none;
text-align: center;
width: auto;
padding: 5em 0 1em;
font-size: 3em;
#suites .imgPlate,
#suites .box
border-width: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
#suites
text-align: center;
#suites .box
float: none;
clear: none;
display: inline-block;
width: auto;
min-width: auto;
#suites .box h2
margin-top: 1em;
#draggable
cursor: pointer;
position: absolute;
top: 210px;
left: 30px;
border: 1px solid #ff8000;
width: 78px;
height: 78px;
border-radius: 37px;
box-shadow: 2px 0 10px #9d9d9d;
background: #ffcc00 url(../../web/dragdrop/draggable.png) 50% 50% no-repeat;
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, -moz-linear-gradient(top, #ffcc00 0%, #ff8000 100%);
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffcc00), color-stop(100%,#ff8000));
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, -webkit-linear-gradient(top, #ffcc00 0%,#ff8000 100%);
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, -o-linear-gradient(top, #ffcc00 0%,#ff8000 100%);
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, -ms-linear-gradient(top, #ffcc00 0%,#ff8000 100%);
background: url(../../web/dragdrop/draggable.png) 50% 50% no-repeat, linear-gradient(top, #ffcc00 0%,#ff8000 100%);
#draggable.hollow
cursor: default;
background: #ececec;
border-color: #cbcbcb;
/* Box Styles */
.box
margin: 4.5em 7.5em;
padding: 3em;
background-color: rgba(20,53,80,0.038);
border: 1px solid rgba(20,53,80,0.05);
.demo-section
margin: 0 auto 4.5em;
padding: 3em;
border: 1px solid rgba(20,53,80,0.14);
.demo-section:not(.wide),
#example .box:not(.wide)
max-width: 400px;
.box:after,
.demo-section:after
content: "";
display: block;
clear: both;
height: 0;
#example .box
margin: 4.5em auto;
#example .box:first-child
margin-top: 0;
.demo-section.k-content
box-shadow: 0 1px 2px 1px rgba(0,0,0,.08), 0 3px 6px rgba(0,0,0,.08);
.box h4,
.demo-section h4
margin-bottom: 1em;
font-size: 12px;
line-height: 1em;
font-weight: bold;
text-transform: uppercase;
.box-col
display: block;
float: left;
padding: 0 3em 1.667em 0;
.box ul:not(.km-widget) li,
.demo-section .box-col ul:not(.km-widget) li
line-height: 3em;
.box li:last-child
margin-bottom: 0;
.box li a
font-size: 13px;
.box .k-widget
background-color: #ebeef0;
border-color: #ccc;
color: #7c7c7c;
.box .k-widget.k-slider
background-color: transparent;
.box .k-button
cursor: pointer;
border-radius: 2px;
font-size: inherit;
color: #333;
background: #e2e4e7;
border-color: #e2e4e7;
min-width: 90px;
box-shadow: none;
.box .k-upload-status .k-button-bare
min-width: 0;
.box .k-button:hover,
.box .k-button:focus:active:not(.k-state-disabled):not([disabled]),
.box .k-button:focus:not(.k-state-disabled):not([disabled])
background: #cad0d6;
border-color: #cad0d6;
color: #000;
box-shadow: none;
.box .k-primary
color: #fff;
background: #015991;
border-color: #015991;
.box .k-primary:hover,
.box .k-primary:focus:active:not(.k-state-disabled):not([disabled]),
.box .k-primary:focus:not(.k-state-disabled):not([disabled])
background: #013A5E;
border-color: #013A5E;
color: #fff;
.box .k-textbox,
.box textarea
background: #fff;
border-color: #e2e4e7;
color: #555;
border-radius: 2px;
.box .k-textbox:hover,
.box .k-textbox:active,
.box .k-textbox:focus,
.box textarea:hover,
.box textarea:active,
.box textarea:focus
border-color: #cad0d6;
background: #fff;
color: #333;
box-shadow: none;
.box.demo-description p
line-height: 1.5em;
max-width: 1000px;
padding-bottom: 1em;
.box.demo-description p:last-child
padding-bottom: 0;
.box.demo-description ul,
.box.demo-description ul li
list-style: disc inside;
line-height: 1.5em;
max-width: 1000px;
.box.demo-description ol,
.box.demo-description ol li
list-style: decimal inside;
line-height: 1.5em;
max-width: 1000px;
.box.demo-description ul,
.box.demo-description ol
margin: 1em;
padding: 0;
.demo-hint
line-height: 22px;
color: #aaa;
font-style: italic;
font-size: .9em;
padding-top: 1em;
.responsive-message
font-size: 17px;
display: none;
margin: 4em auto;
padding: 2.5em;
text-align: center;
background-color: #ffda3f;
color: #000;
.responsive-message:before
content: "This demo requires browser or device screen width to be equal or greater than 1024px.";
@media screen and (max-width: 1023px)
.page
max-width:100%;
margin: 0;
padding: 10px;
background: #fff;
border: 0;
.hidden-on-narrow
display: none !important;
.responsive-message
display: block;
div.console div
height: auto;
<!DOCTYPE html>
<html>
<head>
<base href="https://demos.telerik.com/kendo-ui/grid/remote-data-binding">
<style>html font-size: 14px; font-family: Arial, Helvetica, sans-serif; </style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.default-v2.min.css" />
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example">
<div id="grid"></div>
<div class="box wide">
<h4>Console log</h4>
<div class="console"></div>
</div>
</div>
</body>
</html>
【问题讨论】:
【参考方案1】:这个问题似乎是设计的,在不久的将来不会改变。
我们正在考虑改进数据源请求。目前的 state 有两个调用,因为我们使用第一个来重置 数据源的状态和第二个应用排序的状态。
来源:https://github.com/telerik/kendo-ui-core/issues/5462#issuecomment-563259073
【讨论】:
这个问题有补丁/更新吗?剑道解决了这个问题吗? 据我所知不是这样。问题仍然存在。【参考方案2】:不知道如何预防。
在 kendo.all.js 的深处,在 FilterMenu 小部件过滤器方法中,似乎发生了加倍:
filter: function (expression)
var filters = this._stripFilters(expression.filters);
if (filters.length && this.trigger('change',
filter:
logic: expression.logic,
filters: filters
,
field: this.field
))
return;
expression = this._merge(expression);
if (expression.filters.length)
this.dataSource.filter(expression);
,
在导致加载数据页面的滚动后第一次,UI 过滤将导致:
this.trigger('change',
发出导致第一个dataBound
的请求,并且
this.dataSource.filter(expression);
发出导致第二个dataBound
的请求
查看调试器网络选项卡,您将看到框架发出两个GET
请求。 (我将页面大小更改为 8,因此 URL 参数有 top=8
):
https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders?$callback=jQuery1123011816937403352101_1583588644905&%24inlinecount=allpages&%24format=json&%24top=8
https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders?$callback=jQuery1123011816937403352101_1583588644905&%24inlinecount=allpages&%24format=json&%24top=8&%24filter=startswith(ShipName%2C%27h%27)
最佳回复可能来自Progress forums。您可能需要注册或获得许可才能在此处发布新问题。
【讨论】:
感谢您的努力和回答。与此同时,我从 Telerik 团队找到了关于这个问题的答案。查看接受的答案。以上是关于如果启用了无限滚动,如何防止剑道网格两次加载数据?的主要内容,如果未能解决你的问题,请参考以下文章