2009-05-22 45 views
0

的,而在这个函数语句运行太慢提高效率(防止4-5秒,页面加载)在IE/Firefox,但很快在Safari ...在jQuery函数

它测量上的文字的像素宽度一个页面截断,直到文本达到理想的宽度:

function constrain(text, ideal_width){ 

    $('.temp_item').html(text); 
    var item_width = $('span.temp_item').width(); 
    var ideal = parseInt(ideal_width); 
    var smaller_text = text; 
    var original = text.length; 

    while (item_width > ideal) { 
     smaller_text = smaller_text.substr(0, (smaller_text.length-1)); 
     $('.temp_item').html(smaller_text); 
     item_width = $('span.temp_item').width(); 
    } 

    var final_length = smaller_text.length; 
    if (final_length != original) { 
     return (smaller_text + '…'); 
    } else { 
     return text; 
    } 
} 

任何方式来提高性能?我将如何将其转换为冒泡排序功能?

谢谢!

+0

这不是一个真正的排序问题,而且气泡排序也是你能做的最慢的排序。 – Soviut 2009-05-22 01:33:06

回答

5

将调用移至循环外部的$(),并将其结果存储在临时变量中。除了调用.html()之外,运行该函数将成为代码中最慢的事情。

他们非常努力地使库中的选择器引擎变得很快,但与普通的javascript操作相比,它仍然很慢(比如在本地范围内查找变量),因为它必须与dom进行交互。特别是如果您使用类似的类选择器,jquery必须遍历文档中的每个元素,查看每个类属性并在其上运行正则表达式。每一个循环!尽可能多地从紧密的环路中取出尽可能多的东西。 Webkit运行速度很快,因为它具有.getElementsByClassName,而其他浏览器则没有。 (然而)。

+0

这似乎是合理的,没有尝试过自己。不知道是否调用html()在DOM中插入较短的字符串也有牵连(即它们是否触发渲染)? – 2009-05-22 01:34:03

+0

是的,这应该工作。它将使您的代码更快,但可能更重要的是,更易于维护,符合DRY原则。 例如,如果您认识到temp_item实际上应该是一个id而不是一个类,则必须在四个位置更改代码。想念一个人,你可能会拉你的头发一段时间。 如果你按照布列塔尼的建议,你只需要做一个改变。 – 2009-05-22 01:57:55

4

而不是一次删除一个字符,直到找到理想的宽度,您可以使用binary search

2

我看到问题在于你不断修改循环中的DOM,方法是设置temp_item的html,然后重新读取宽度。

我不知道你的问题的上下文,但从我的角度来看,通过测量渲染元素来调整布局并不是一个好习惯。

也许你可以从不同的角度来解决问题。截断为固定宽度是常见的。

其他可能性(hack?)如果没有选择,可以使用容器元素的溢出css属性,并把…在文本旁边的其他元素中。虽然我建议你重新思考解决问题的方式,你的意图。

雨果

2

除了由布雷顿的建议,另一种可能性,以加快你的算法是使用上的文字长度的二进制搜索。目前,您一次只能减少一个字符的长度 - 这是字符串长度中的O(N)。相反,使用将会是O(log(N))的搜索。

粗略地说,这样的事情:

function constrain(text, ideal_width){ 

...

var temp_item = $('.temp_item'); 
    var span_temp_item = $('span.temp_item'); 

    var text_len_lower = 0; 
    var text_len_higher = smaller_text.length; 

    while (true) { 
      if (item_width > ideal) 
      { 
      // make smaller to the mean of "lower" and this 
      text_len_higher = smaller_text.length; 
      smaller_text = text.substr(0, 
       ((smaller_text.length + text_len_lower)/2)); 
      } 
      else 
      { 
      if (smaller_text.length>=text_len_higher) break; 

      // make larger to the mean of "higher" and this 
      text_len_lower = smaller_text.length; 
      smaller_text = text.substr(0, 
       ((smaller_text.length + text_len_higher)/2)); 
      } 
      temp_item.html(smaller_text); 
      item_width = span_temp_item.width(); 
    } 

... }

1

有一点要注意的是,每次添加的东西到DOM或更改节点中的html,页面必须重绘本身,这是一项昂贵的操作。在循环之外移动任何HTML更新可能有助于加快速度。

正如其他人所提到的,您可以将调用移动到$()以外的循环。您可以创建对该元素的引用,然后只需在循环中调用其中提到的1800信息即可。

如果您使用带有Firebug插件的Firefox,则有一种分析代码的好方法,可以查看哪些时间最长。只需点击第一个标签下的配置文件,执行操作,然后再次点击配置文件。它会显示一个表格,其中包含代码每个部分的时间。很有可能你会在列表中看到js框架库中的很多东西;但是你可以通过一些试验和错误来分离它。