Javascript 高性能dom添加和删除
旁注:我使用的是JQuery,但不是任何第三方表组件(目前也不能) 我的问题是,我应该能够显示大量(10000条)经过的消息——每秒都会有数百条新消息,它们应该添加到底部。当我们达到10000条限制时,旧消息将从一开始就被删除 还应该可以过滤这些消息,因此当用户在搜索框中键入内容时,只会显示包含单词的行 网站结构很简单:Javascript 高性能dom添加和删除,javascript,jquery,performance,dom,Javascript,Jquery,Performance,Dom,旁注:我使用的是JQuery,但不是任何第三方表组件(目前也不能) 我的问题是,我应该能够显示大量(10000条)经过的消息——每秒都会有数百条新消息,它们应该添加到底部。当我们达到10000条限制时,旧消息将从一开始就被删除 还应该可以过滤这些消息,因此当用户在搜索框中键入内容时,只会显示包含单词的行 网站结构很简单: <div id="message_container"> <p>Message 1</p> <p>Message 2<
<div id="message_container">
<p>Message 1</p>
<p>Message 2</p>
<p>Message 3</p>
<p>Message 4</p>
</div>
信息1
信息2
信息3
信息4
目前我一次添加多条消息,速度非常快:
var newMessagesHtml = [];
// messages = new messages
for(var ii = 0; ii < messages.length; ii ++) {
newMessagesHtml.push("<p>Message</p>");
}
$("#message_container").append(newMessagesHtml.join(''));
var newMessagesHtml=[];
//消息=新消息
对于(var ii=0;ii”;
}
$(“#消息_容器”).append(newMessagesHtml.join(“”));
我认为这不是问题(我缓存了message_容器的查询)。然而,当我们达到10000条限制并开始从顶部删除旧消息时,这是很慢的。应该怎么做?我尝试使用jquery过滤n条第一条消息并将其删除,但浏览器开始变得无响应。一次删除多条消息更好,还是一次删除一条消息更好
如果没有第三方组件(JQuery除外),您将如何实现这些功能?
1) 每秒添加和删除许多元素
2) 过滤掉我们不想看到的元素
感谢所有的帮助和想法。选项1:
不要使用jQuery或HTML字符串。而是将消息创建为DOM元素,并使用JavaScript调用附加/删除它们,如:
var newMessagesHtml = [];
var container = document.getElementById('message_container');
for(var ii = 0; ii < messages.length; ii ++) {
var msg = document.createElement('p');
msg.appendChild(document.createTextNode(messages[i]));
container.appendChild(msg);
}
备选案文2:
你可以试试。它管理一个虚拟DOM并最小化对真实DOM的更新(这是一个瓶颈)。对于一个实际的半实现,您可以尝试这样做。我在上面添加了@josdejong的提示,以便能够顺利地添加/删除/搜索 QueryList类增加了添加/删除消息的可能性,QueryList.items包含实际项目的列表,通过设置maxItems,您可以轻松配置要查看的项目数:) 添加时添加dom元素,删除时再次删除dom元素,搜索仅切换css类(删除父dom节点) 示例可在此处找到: 查询列表的代码
;(function($) {
function QueryItem(parentElement, value) {
this.parentElement = parentElement;
this.value = value;
this.element = undefined;
}
function QueryList(element, options) {
var that = this;
this.items = [];
this.currentQuery = undefined;
this.suspendLayout = function() {
element._oldNode = element.parentNode;
element.parentNode.removeChild(element);
};
this.resumeLayout = function() {
element._oldNode.appendChild(element);
};
this.add = function(item) {
var p, qry = new QueryItem(element, item);
var p = document.createElement('p');
if (this.currentQuery && item.indexOf(this.currentQuery) === -1) {
p.className = 'hidden';
}
p.innerHTML = qry.value;
qry.element = p;
qry.parentElement = element;
qry.parentElement.appendChild(p);
this.items.push(qry);
if (this.items.length > options.maxItems) {
this.remove(0, this.items.length - options.maxItems);
}
}
this.remove = function(index, length) {
var i, item, len;
for (i = 0, len = length || 1; i < len; i++) {
item = this.items[index];
item.parentElement.removeChild(item.element);
item.element = undefined;
}
this.items.splice(index, length);
};
this.search = function(txt) {
var i, len, item;
this.currentQuery = txt;
this.suspendLayout();
for (i = 0, len = this.items.length; i < len; i++) {
item = this.items[i];
if (txt && item.value.indexOf(txt) === -1) {
item.element.className = 'hidden';
} else {
item.element.className = '';
}
}
this.resumeLayout();
};
}
$.fn.queryList = function(options) {
if (typeof this.selector === 'undefined' || this.length !== 1) {
throw 'QueryList has to be linked to exactly one item';
}
var qry = new QueryList(this[0], options);
this.data('queryList', qry);
return qry;
};
})(jQuery);
;(函数($){
函数QueryItem(parentElement,value){
this.parentElement=parentElement;
这个值=值;
this.element=未定义;
}
函数查询列表(元素、选项){
var=这个;
此参数为.items=[];
this.currentQuery=未定义;
this.suspendLayout=函数(){
元素。_oldNode=element.parentNode;
element.parentNode.removeChild(元素);
};
this.resumeLayout=函数(){
元素。\u oldNode.appendChild(元素);
};
this.add=函数(项){
var p,qry=新查询项(元素,项目);
var p=document.createElement('p');
if(this.currentQuery&&item.indexOf(this.currentQuery)=-1){
p、 className='hidden';
}
p、 innerHTML=qry.value;
qry.element=p;
qry.parentElement=元素;
qry.parentElement.appendChild(p);
本.项目.推送(qry);
if(this.items.length>options.maxItems){
this.remove(0,this.items.length-options.maxItems);
}
}
this.remove=函数(索引、长度){
变量i,项目,len;
对于(i=0,len=length | | 1;i
并作为试验的主要方法
$(function() {
var queryList = $('#msgContainer').queryList({
maxItems: 10000
}), index = 0, i, interval;
queryList.add('hi there');
for (i = 0; i < 7000; i++) {
queryList.add('item ' + i);
}
console.log(queryList.items);
$('#buttonSearch').on('click', function(e) {
var svalue = $('#inputSearch').val();
queryList.search(svalue);
});
interval = setInterval(function() {
queryList.suspendLayout();
for (var i = 0; i < 100; i++) {
queryList.add('Additional message ' + ((index * 100) + i));
}
queryList.resumeLayout();
index++;
}, 1000);
$('#buttonStopInterval').on('click', function(e) {
clearInterval(interval);
});
});
$(函数(){
变量queryList=$('#msgContainer')。queryList({
最大项数:10000
}),指数=0,i,区间;
添加('hi there');
对于(i=0;i<7000;i++){
queryList.add('item'+i);
}
日志(queryList.items);
$(“#按钮搜索”)。在('click',函数(e){
var svalue=$('#inputSearch').val();
查询列表搜索(svalue);
});
间隔=设置间隔(函数(){
suspendLayout();
对于(变量i=0;i<100;i++){
add('附加消息'+((索引*100)+i));
}
queryList.resumeLayout();
索引++;
}, 1000);
$('#buttonStopInterval')。在('click',函数(e)上{
间隔时间;
});
});
哦,我刚刚尝试从dom中删除容器以附加节点,但这不会使现有消息从浏览器中消失吗?没有意识到。不,如果你在最后一个容器中再附加一个容器。在执行大量DOM操作时,它可以更快,但也可以更慢。你必须测试它是否能提高体育成绩
$(function() {
var queryList = $('#msgContainer').queryList({
maxItems: 10000
}), index = 0, i, interval;
queryList.add('hi there');
for (i = 0; i < 7000; i++) {
queryList.add('item ' + i);
}
console.log(queryList.items);
$('#buttonSearch').on('click', function(e) {
var svalue = $('#inputSearch').val();
queryList.search(svalue);
});
interval = setInterval(function() {
queryList.suspendLayout();
for (var i = 0; i < 100; i++) {
queryList.add('Additional message ' + ((index * 100) + i));
}
queryList.resumeLayout();
index++;
}, 1000);
$('#buttonStopInterval').on('click', function(e) {
clearInterval(interval);
});
});