Fwd: 关于lazyload的提案

Looping Franky


---------- 已转发邮件 ----------
发件人: Huan Du <dh20156@gmail.com>
日期: 2012年2月13日 下午5:22
主题: 关于lazyload的提案
收件人: public-html-ig-zh@w3.org
抄送: 程劭非 <csf178@gmail.com>, "Kang-Hao (Kenny) Lu" <kennyluck@w3.org>,
otakustay@gmail.com


Hi All,

近日,“*WEB标准翻译与贡献*”QQ群成员向*WHATWG*提交了一个关于*lazyload*的提案。

如大家所知,WEB的发展已经让更多的人认为,可以通过它在互联网上创建越来越丰富的内容和应用,但是受限于目前的网络环境,我们在创建应用时需要尽可能多地去考虑性能问题,比如,图片的延迟加载。

在一些访问量巨大的应用中,我们通常需要将不在”可视范围“内的图片进行延迟加载的处理,以便整个页面能够更快的呈现给用户,并且节省带宽。当前,多数的做法大概可以总结如下:


   1.  后端输出HTML时,所有需要LazyLoad的<img>标签的*src*属性设置为一张1x1的透明的gif图片,如*
   transparent.gif*,并将真实的图片地址设置在*data-src*属性上

   <img src="/images/transparent.gif" data-src="/images/real.png" />

   2. 监听window.onscroll事件

   window.onscroll = lazyLoadImages;

   3. 在事件中,找出所有需要LazyLoad且在可视区域中的<img>标签,并设置其*src*属性为预先存储的*data-src*属性。

function lazyLoadImages() {
    var images = document.getElementsByTagName('img');
    for (var i = images.length - 1; i >= 0; i--) {
        var image = images[i];
        var src = image.getAttribute('data-src');
        if (src && isVisible(image)) {
            image.src = src;
            image.removeAttribute('data-src');
        }
    }
}

function isVisible(element) {
    var style = window.getComputedStyle(element, null);
    if (style.getPropertyValue('display') === 'none') {
        return false;
    }
    if (style.getPropertyValue('visibility') === 'hidden') {
        return false;
    }

    return isInViewport(element);
}

应用这种解决方案,我们确实可以解决延迟加载的问题,不过这其中会遇到的问题也不少:


   1.  onscroll 不好計算,且用到boundingClientRect等会引起强制Layout,影响性能

 无法依靠浏览器的更多资源来进行策略的选择,如:

   1.  Reflow/Repaint不频繁时默认多加载图片
   2.  网络条件良好,带宽剩余较多时自动加载图片
   3.  根据用户的浏览习惯,多加载1-2屏的数据

这时,我们就忍不住要想,如果HTML或DOM中能够提供一些新的特性去对此作出支持,那可能会是一件很好的事情!

有没有必要呢?我想,一切能够对WEB发展起到积极正面作用的改善,都是有意义的。于是,通过大家的讨论,我们初步提出了以下几点提案:

方案1. 增加onscrollintoview和onscrolloutofview事件

给Element添加2个事件:

   -  onscrollintoview:当滚动条滚动后,元素进入到可视区域时触发
   -  onscrolloutofview:当滚动条滚动后,元素离开可视区域时触发


方案2. 增加DOMVisibilityChanged事件

给Element增加一个Mutation Event,名为DOMVisibilityChanged,在元素满足以下条件时触发且visibility为true:

   -  元素的BoundingClientRect与可视区域相交
   -  元素的display样式非none
   -  元素的visibility样式非hidden

当以上任一条件改变时,触发事件,且visibility为false

方案3. 为所有加载外部资源的元素加入defer属性

给需要加载外部资源的元素,如img、iframe等加载一个defer属性

defer属性为Boolean Attribute,为true时表示在浏览器优化的特定情况下才开始加载,包括:

   - 在可视区域或可视区域外(诸如)1屏范围内
   - 元素可见(display/visibility)
   - 带宽有空余
   - 页面当前Layout/Paint不频繁,有足够空余来完成图片/iframe的渲染


方案4. 为所有加载外部资源的元素加入deferpolicy属性

deferpolicy属性是一个Enumrable Attribute,值有以下:

   - visibile:进入可视区域时加载
   - network-idle:当网络空闲时加载
   - render-idle:当渲染空闲时加载

以上规则可任意组合,无此属性则视为立刻加载
限于内容篇幅,更详细内容请移步:http://www.w3.org/html/ig/zh/wiki/Proposals/img_lazyload

在此发送此邮件的目的是希望小组中更多人能够看到并参与到对此提案的讨论中来,如果你有任何意见或建议,我们非常期望与大家一起讨论。

感谢 Kenny Luck, GZhang, Franky, Winter及其他各位的贡献。

Regards,

杜欢

Received on Monday, 13 February 2012 10:38:15 UTC