当列表包含太多dom元素时,页面会冻结标签

jba*_*sta 9 html css optimization dom responsive-design

我有一个包含两列的网页,一个带导航栏和页脚的页眉.

左列用于列出三个不同选项卡中的项目.每个选项卡都包含其项目的类型.

右侧包含一个或多个显示项目的地图.

选择包含太多元素的选项卡时会发生此问题.

它冻结了交互(突出显示,添加/删除DOM和动画),打破了它的响应能力.

即使它不是与所选标签的交互(即鼠标悬停在导航栏链接上).

但是,当所选标签的项目较少时,页面的响应性很好.

我创建了一个尖峰解决方案来向您展示我在说什么.

请你记住,这是我的问题的一个更简单的版本.这只是一个举例说明我的案例.

$('#nav-tabs a').click(function (e) {
  e.preventDefault()
  $(this).tab('show')
});

$('#addBox').on('click', function () {
  $("#content").append("<div class='box pull-left'></div>");
});

$('#newPapper').on('click', function () {
  $("#content").empty();
});


$('#addOne').on('click', function () {
  $("#home div.panel-default").append(createContactDom());
});

$('#addThousand').on('click', function () {
  var dom = "";
  for(var i = 5000; i > 0; i--){
    dom+=createContactDom();
  }
  $("#home div.panel-default").append(dom);
});

$('#clean').on('click', function () {
  $("#home div.panel-default").empty();
});

function createContactDom(){

  var age = Math.round(Math.random()*100);
  var birthday = moment().subtract(age, 'years');
  var isFemale = Math.random() > 0.4;
  var nameIndex = Math.floor(Math.random() * names[isFemale ? "female" : "male"].length);
  var surnameIndex = Math.floor(Math.random() * surnames.length)
  var name = names[isFemale ? "female" : "male"][nameIndex] + " " + surnames[surnameIndex];
  
  var html = '<div id="p' + birthday.format("X") + '" class="panel-heading">';
  html += '<span class="fa-stack fa-lg custom-stack pull-left font-grey-gallery" >';
  html += '<i class="fa fa-square-o fa-stack-2x"></i>';
  html += '<i class="fa fa-user fa-stack-1x"></i>';
  html += '</span>';
  html += '<div class="pull-left">';
  html += '<div class="title">';
  html += '<span >' + name + '</span> ';
  html += '</div>';
  html += '<div class="sub-title">';
  html += '<span title="' + (isFemale ? 'She': 'He') + ' was born on a ' + birthday.format('dddd') + ' at ' + birthday.format('HH:MM a') + '" class="badge pull-left" >' + birthday.format("YYYY/MM/DD") +'</span>';
  html += '<span title="It is a ' + (isFemale ? 'female' : 'male') + '" class="badge pull-left ' + (isFemale ? 'female' : 'male') + '" >' + (isFemale ? 'Female' : 'Male') + '</span>';
  html += '<div class="clearfix"></div>';
  html += '</div>';
  html += '</div>';
  html += '<div class="pull-right actions">';
  html += '<a id="d' + birthday.format("X") + '" title="Delete contact" class="fa fa-times fa-times-close"  style="color: rgb(87, 142, 190);" onclick="deleteContact(this)"></a>';
  html += '</div>';
  html += '<div class="clearfix"></div>';
  html += '</div>';
  
	return html;                      
}


deleteContact = function(e){
  $("#" + e.id.replace("d", "p")).remove();
}

var names = {
  female: ["Maria","Leonor","Matilde","Beatriz","Carolina","Mariana","Ana","Inês","Margarida","Sofia"],
  male: ["João", "Martim", "Rodrigo", "Santiago", "Francisco", "Afonso", "Tomás", "Miguel", "Guilherme", "Gabriel"]
}
var surnames = ["Silva", "Santos", "Ferreira", "Pereira", "Oliveira", "Costa", "Rodrigues", "Martins", "Jesus", "Sousa", "Fernandes", "Gonçalves", "Gomes", "Lopes", "Marques", "Alves", "Almeida", "Ribeiro", "Pinto", "Carvalho"]
Run Code Online (Sandbox Code Playgroud)
.row{
  height: 600px;
}

.col-sm-5,
.col-sm-7{
  height: inherit;
}

.tab-content{
  height: inherit;
  overflow-y: auto;  
}

button{
  margin-top: 5px;
}
span.badge{
  margin-right: 5px;
}

.badge{
   background-color: #999 !important;
}
.badge.female{
   background-color: pink !important;
}
.badge.male{
   background-color: #1c90f3 !important;
}

#content{
  height: inherit;
  overflow-y: auto;  
  padding-top: 5px;
}

#content .box{
  width: 100px;
  height: 100px;
  background-color: green;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
  <div class="col-sm-5">
    <ul class="nav nav-tabs" id="myTabs" role="tablist"> 
      <li role="presentation" class="active">
        <a href="#home" id="home-tab" role="tab" data-toggle="tab" aria-controls="home" aria-expanded="true">Contacts</a>
      </li> 
      <li role="presentation" class="">
        <a href="#profile" role="tab" id="profile-tab" data-toggle="tab" aria-controls="profile" aria-expanded="false">Problem?</a>
      </li> 
      <li>
        <button type="button" id="addOne" class="btn btn-sm">+</button>
        <button type="button" id="addThousand" class="btn btn-sm btn-primary">+5k</button>
        <button type="button" id="clean" class="btn btn-sm">clean</button>
      </li>
    </ul>

    <div class="tab-content" id="myTabContent"> 
      <div class="tab-pane fade active in" role="tabpanel" id="home" aria-labelledby="home-tab">
        <div class="panel panel-default" style="border-left: 3px solid rgb(87, 142, 190);" >
        </div> 
      </div> 
         
      <div class="tab-pane fade" role="tabpanel" id="profile" aria-labelledby="profile-tab"> 
        <h1>Problems to solve:</h1>
        <ul>
          <li>Adding 5k new contacts blocks the browser's page</li>
          <li>Switching between the two tabs blocks the browser's page</li>
          <li>Painting freezes when adding 5k new contacts</li>
        </ul> 
        <p>Note: The problems get worse as may contacts you add...</p>
      </div>
    </div>
  </div>

  <div class="col-sm-7">
    <button tyoe="button" id="addBox" class="btn btn-sm btn-primary">Paint</button>
    <button tyoe="button" id="newPapper" class="btn btn-sm">New papper</button>
    <div id="content"></div>
  </div>
  
</div>
Run Code Online (Sandbox Code Playgroud)


我已经在使用chrome开发人员工具捕获时间轴的操作.到目前为止,我可以看到,问题是jquery在布局渲染中的一些回流.

这是我的时间轴的截图: 在此输入图像描述

如何优化我的DOM操作以避免页面冻结?在我这样说之前,我可以告诉浏览器不要重绘左列吗?

小智 5

为什么不对这么大的表使用虚拟滚动无限滚动分页,而不是在启动时创建它?

有很多例子:https: //www.sitepoint.com/jquery-infinite-scrolling-demos/

将5k对象放在一行中太多了,imo.

在您的情况下,您将需要拆分/中断dom操作循环以获取堆栈/事件循环中的其他内容.

$('#addThousand').on('click', function () {
  for(var i = 5000; i > 0; i--){
  setTimeout( function() {
    var dom=createContactDom();
    $("#home div.panel-default").append(dom);
    }, 0);
  }

});
Run Code Online (Sandbox Code Playgroud)

或事件:

$('#addThousand').on('click', function () {
  for(var i = 5000; i > 0; i--){
  setTimeout( function() {
    var dom=createContactDom();
    $("#home div.panel-default").append(dom);
    }, i);
  }

});
Run Code Online (Sandbox Code Playgroud)