基于会话 DOM 实时应用程序中的对象可见性操作
Session based DOM object visibility manipulation in real time application
我正在开发一个远程监控应用程序并且有一个问题,我想看看我是否可以得到一些关于如何最好地解决的想法。
当服务器确定数据库中有新信息要显示给客户端时,它会调用 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">
(...)
这里有两种可能的设计路径:
切换为仅更新数据,而不是 HTML。 更改更新页面的方式,以便仅更新页面中的数据而不是替换 HTML。这将需要重组获取和应用更新的方式,但会保留页面中的所有 HTML 元素,因此可见性状态也会保留。为此,您可能会从服务器请求 JSON 数据,然后您的客户端代码会将这些数据填充到当前的 HTML 中。这显然比您现在所做的工作更多,但具有保留所有 DOM 状态的优势,因为 DOM 元素未被替换(某些文本节点除外)。
保存可见性状态,然后在更新 DOM 后恢复该状态。 如果您要将 DOM 对象替换为new HTML,那么您需要保存原始 DOM 的可见性设置,然后在替换为 DOM 的新部分后,您必须将那些早期的可见性设置应用到新的 DOM 元素。这需要能够将旧 DOM 元素映射到相应的新 DOM 元素。如果您知道 table 行结构保持不变,而您只是 showing/hiding 行,那么您实际上可以在您的代码(例如 var hiddenRows = [1,5,6,7,10]
)之前创建一个隐藏行号数组替换 DOM 的部分,然后放入新的 HTML,然后隐藏数组中列出的每一行。
我正在开发一个远程监控应用程序并且有一个问题,我想看看我是否可以得到一些关于如何最好地解决的想法。
当服务器确定数据库中有新信息要显示给客户端时,它会调用 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">
(...)
这里有两种可能的设计路径:
切换为仅更新数据,而不是 HTML。 更改更新页面的方式,以便仅更新页面中的数据而不是替换 HTML。这将需要重组获取和应用更新的方式,但会保留页面中的所有 HTML 元素,因此可见性状态也会保留。为此,您可能会从服务器请求 JSON 数据,然后您的客户端代码会将这些数据填充到当前的 HTML 中。这显然比您现在所做的工作更多,但具有保留所有 DOM 状态的优势,因为 DOM 元素未被替换(某些文本节点除外)。
保存可见性状态,然后在更新 DOM 后恢复该状态。 如果您要将 DOM 对象替换为new HTML,那么您需要保存原始 DOM 的可见性设置,然后在替换为 DOM 的新部分后,您必须将那些早期的可见性设置应用到新的 DOM 元素。这需要能够将旧 DOM 元素映射到相应的新 DOM 元素。如果您知道 table 行结构保持不变,而您只是 showing/hiding 行,那么您实际上可以在您的代码(例如
var hiddenRows = [1,5,6,7,10]
)之前创建一个隐藏行号数组替换 DOM 的部分,然后放入新的 HTML,然后隐藏数组中列出的每一行。