我正在开发一个远程监控应用程序,如果我能就如何最好地解决问题得到一些想法,我希望看到这个问题。
当服务器确定数据库中有新信息要显示给客户端时,它会调用SignalR客户端方法,该方法请求新的部分视图。
在主页面上,我有一个简单的JQuery脚本,可以切换表格的可见性,以及部分视图中包含的子行。
现在问题应该很明显了。当AJAX使用新返回的局部视图更新DOM时,局部视图中的对象将返回到其初始默认可见性状态。这是完全可以预料到的,但是我希望在整个连接的客户端会话中使每个元素的可见性状态保持不变。
部分视图中的数据基本保持不变(就正常实时操作而言,不必担心添加或删除表格或行)。
守则:
JQuery控件:(未优化,但正在运行)
$("#systemDetails").on("click", "#deviceDetail", function () {
if ($(this).closest('tr').next().is(':hidden')) {
$("[id^=child]").hide();
$("[id^=deviceDetail]").removeClass('glyphicon-minus-sign');
$("[id^=deviceDetail]").addClass('glyphicon-plus-sign');
$(this).closest('tr').next().toggle("slow");
$(this).toggleClass("glyphicon-plus-sign glyphicon-minus-sign");
}
else {
$("[id^=child]").hide();
$(this).toggleClass("glyphicon-plus-sign glyphicon-minus-sign");
}
});
$("#systemDetails").on("click", "#categoryToggle", function () {
$(this).closest('table').next().toggle("slow");
$(this).toggleClass("glyphicon-plus-sign glyphicon-minus-sign");
});
主要观点:
@model xxxx.Models.SystemModel
@{
ViewBag.Title = "System Details";
}
<div class="row">
<div class="col-md-12">
<div id="systemDetails">
@Html.Action("GetDetails", "Monitoring", Model.Customer.SONumber)
</div>
</div>
</div>
@section Scripts{
<script src="/Scripts/systemdetails.js"></script>
<script src="/Scripts/jquery.signalR-2.1.2.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.monitoringHub;
//debugger;
// Create a function that the hub can call to broadcast messages.
notifications.client.updateDetails = function (sonumber) {
getDetails(sonumber)
};
// Start the connection.
$.connection.hub.start().done(function () {
//alert("connection started")
getDetails(@Model.Customer.SONumber.ToString());
}).fail(function (e) {
alert(e);
});
});
function getDetails(sonumber) {
if(sonumber = (@Model.Customer.SONumber.ToString())){
var tbl = $('#systemDetails');
$.ajax({
url: '/Monitoring/GetDetails/@Model.Customer.SONumber.ToString()',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html',
cache: false
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
}
</script>
}
部分视图的相关示例:(如果您想查看更多代码,请提出请求)
@foreach (var category in Model.Devices.Select(d => d.Room).Distinct())
{
<table class="table-borderless">
<tr>
<td valign="middle"><i class="glyphicon glyphicon-lg glyphicon-plus-sign" id="categoryToggle"></i></td>
<td><h2 class="tableheader">@category</h2></td>
@if (Model.Devices.Where(d => d.Room == category).Any(d => d.Status == "Offline"))
{
<td valign="middle"><i class="glyphicon glyphicon-lg glyphicon-warning-sign"></i></td>
<td><h2 class="tableheader">@(Model.Devices.Where(d => d.Room == category && d.Status == "Offline").Count())</h2></td>
}
else
{
<td valign="middle"><i class="glyphicon glyphicon-lg glyphicon-ok"></i></td>
}
</tr>
</table>
<table style="display:none" class="table">
(...)
答案 0 :(得分:0)
以下是两种可能的设计路径:
切换到仅更新数据,而不是HTML。更改更新页面的方式,以便仅更新页面中的数据而不是替换HTML。这将需要重新构建您获取和应用更新的方式,但会保留页面中的所有HTML元素,以便保留可见性状态。为此,您可能会从服务器请求JSON数据,然后您的客户端代码将填充到当前HTML中。这显然比你现在所做的工作更多,但是具有保留所有DOM状态的优点,因为DOM元素没有被替换(除了一些文本节点)。
保存可见性状态,然后在更新DOM后恢复该状态。如果要用新的HTML替换DOM对象,则需要保存原始的可见性设置DOM然后在用新的DOM部分替换之后,您必须将这些早期的可见性设置应用于新的DOM元素。这将需要能够将旧的DOM元素映射到相应的新DOM元素。如果您知道表行结构保持相同并且您只是显示/隐藏行,那么您可以在替换DOM部分之前在代码中创建一个隐藏行号数组(例如var hiddenRows = [1,5,6,7,10]
),然后输入新的HTML,然后隐藏数组中列出的每一行。