首页 > 请大神解答Zepto assets模块的原理?

请大神解答Zepto assets模块的原理?

Zepto 的 assets模块,该模块“实验性支持从DOM中移除image元素后清理iOS的内存”,我不明白为什么要这样做,直接将DOM remove掉不就行了吗?希望大神能解答,谢谢!

;(function($){
  var cache = [], timeout

  $.fn.remove = function(){
    return this.each(function(){
      if(this.parentNode){
        if(this.tagName === 'IMG'){
          cache.push(this)
          this.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
          if (timeout) clearTimeout(timeout)
          timeout = setTimeout(function(){ cache = [] }, 60000)
        }
        this.parentNode.removeChild(this)
      }
    })
  }
})(Zepto)

这个要从mobile safari严格的资源占用限制说起;mobile safari要比桌面版的浏览器的资源占用限制严格的多:
https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW15

其中一条相关的限制就是:**When Mobile Safari has loaded between 8 to 10 MB of image data it will simply stop displaying any more images. It might even crash.**

当Mobile Safari加载8-10M左右图像数据的时候,将会停止显示甚至Crash,比如下面的这种应用场景。

为了解决这个问题,我们就要回收掉这些图片资源。

想到的方法一:

var img = document.getElementById('previous');
img.parentNode.removeChild(img);

但是令人遗憾的是,出于某些原因,真正的图片数据根本没法释放,那应该怎么办呢?如果我们用一张非常小的图片替换掉原来的大图片,原来的图片数据是不是就会被清空掉?Let's Try。

能起作用的方法:

var img = document.getElementById('previous');
img.src = 'images/empty.gif';

这个方法貌似起作用了!我们用一张非常小的gif图片变更掉原先图片的src,原来的大图片得到释放了,黑科技万岁啊!但是.......故事显然还没有结束,目前为止,你还需要关注以下三件非常重要的事情:

  1. src替换法不会使得图片资源马上释放,垃圾回收机制将在相当长的一段时间后才能回收掉这些内存资源,因此,当你在使用场景里太快的添加img资源的时候,还是会发生讨厌的事情!

  2. Mobile Safari似乎不能再加载额外的图像资源,即使我们用了上面的黑科技回收掉了一部分或者全部的资源,除非重新加载整个页面来进行测试验证,这tm真是快把人逼疯了。

  3. 如果你想要在DOM中移除image元素,在变更src之前你还必须确保这个element没有被垃圾回收处理掉,不然老图片数据也有可能在这种情况下不得释放。

因此,终极的解决方案应该是:

var img = document.getElementById('previous');
img.parentNode.removeChild(img);
img.src = 'data:image/gif;base64,' + 
      'R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
window.timeout(function() {
img = null;
}, 60000);

这个故事的由来和贡献者来自于这个博客内容:http://www.fngtps.com/2010/mobile-safari-image-resource-limit-workaround/,正是这个作者向zepto贡献了这个黑科技。
作者还测试了一下assets插件~

【热门文章】
【热门文章】