$("#chapters li").show()引发的问题

Feb 4, 2015

259

上周,主要开发项目中APP的内嵌页,前端主要采用的是Zepto.js,其中有一个是显示电子书的目录列表,采用的是li,目录显示效果如下图,当点击更多目录时显示全部列表项。

目录结构如下:

<ul id="chapters">
   <li><a href="#1">章节1</a></li>
   <li><a href="#2">章节2</a></li>
   <li><a href="#3">章节3</a></li>
   <li><a href="#4">章节4</a></li>
</ul>
<a href="javascript:void(0);" id="more">更多目录</a>

当点击更多目录时,直接使用$("#chapters li").show()显示出所有列表项,在chrome仿真器中,一瞬间就可以显示出来,但在真机中,浏览器竟然出现假死的现象,大概会出现5s的卡顿,主要一个原因是有一些电子书有900多个章节。我尝试使用变量把DOM结果集缓存起来,还是会出现卡顿的现象。

翻看Zepto.js的源码,查看show()方法的实现:

show: function(){
  return this.each(function(){
    this.style.display == "none" && (this.style.display = '')
    if (getComputedStyle(this, '').getPropertyValue("display") == "none")
      this.style.display = defaultDisplay(this.nodeName)
  })
}

show()会遍历每一个li,每遍历一个li,如果display属性为none,就会设置一次display属性,DOM树就会渲染一次。如果有900多个li,DOM就会渲染900多次,在PC上问题不大,但在手机上,由于内存较小,就会造成假死的现象。

所以,为了解决这个问题,需要保证每次点击只进行一次DOM渲染,这样才不会出现假死的现象。修改后的代码如下:

//chapters 为ajax获取得到的数据,格式为json
var chaptersLength = chapters.length, //列表项长度
  allChapters = null, //保存全部目录
  lessChapters = null, //保存最少显示的目录
  hideMore = true, //是否隐藏
  $template = '<% _.each(chapters, function(chapter) { %>' + 
    '<li><a href="<%= chapter.url %>" data-chapterid="<%= chapter.chapter_id %>">' +
    '<%= chapter.chapter_title %></a></li><% });%>',//列表显示模板
  $chapters = $("#chapters"), //目录
  $more = $("#more"); //按钮

if (chaptersLength > 4) { //默认显示四个,大于四个时显示更多目录按钮并添加事件
  allChapters = chapters;
  for (var i = 0; i < 4; i++) {
    lessChapters.push(chapters[i]);
  }
	
  renderChapter(lessChapters);
	
  $more.show();
  $more.on("click", function(){
    if (hideMore) {
      hideMore = false;
      $more.text("正在加载");
      setTimeout(function(){ //默认会有几毫秒的延时,主要是为了显示“正在加载”中的状态
        renderChapter(allChapters);
        $more.text("收起目录");
      }, 0);		
    } else {
      hideMore = true;
      renderChapter(lessChapters);
      $more.text("更多目录");
    }
  });
} else {
  renderChapter(chapters);
}

/**
  * 展示列表
  */
function renderChapter(chapters) {
  //这里使用underscore.js _.template()方法
  $chapters.html(_.template($template)({chapters:chapters}));
}

每次处理都是重新写一次DOM树,这样就不会出现卡死的现象。

JavaScript 」相关文章

Wen's Blog

文章归档 » 文章标签 » 博主:吴文伟,Web开发爱好者,专注于前端开发,该博客用于记录和分享平时遇到的一些问题以及知识。

订阅

联系方式

链接