HTML5触摸界面设计与开发--笔记--javaScript性能优化

一 : 本文中使用的性能优化策略

1 只写入DOM,因为DOM交互式相当慢的
测试:

  console.time('test');
  var test=document.getElementById('index-bn').title ;
  console.timeEnd('test');
  test: 0.091ms

  var cache=['111'];
  console.time('test');
  var test=cache[0]; 
  console.timeEnd('test');
  test: 0.021ms
    ```
1.1 显然不可能完全避免从DOM中读取数据,但我们可以使用缓存数据来减少读取的频率,如果你认为会再次使用某个DOM,你可以将它储存在一个变量中。
1.2 DOM操作是阻塞的,当一个DOM操作在运行时,其他的什么都不能做。

2 给用户反馈的优先级是最高的
2.1 输出
浏览器中的javaScript是单线程,这意味着同一时间javaScript引擎在同一时间只能做一件事情,这个线程通常被称为UI线程,并行是通过将所有任务推到一个队列中来实现的,队列中的任务会在线程变得空闲时执行,如果一个缓慢的DOM操作在执行,传入的时间必须排队等候,直到DOM操作完成处理,如一个缓慢的DOM读取在执行,此时用户与页面进行交互,那么事件将不会马上被处理。
2.2 延迟执行
如果浏览器正忙着给用户返回,而你需要处理AJAX响应这种成本比较大的操作,你可以延迟执行。

例 –无限滚动

<div id="wrapper">

</div>
<script id="slide" type="text/x-handlebars">
    <div class="slide">
        <p class="logo"></p>
        <div class="imgholder">
            <a title="by {{ownername}} on Flickr" target="_blank" 
            href="http://www.flickr.com/photos/{{owner}}/{{id}}"><img class="img" data-src="{{url_n}}"></a>
            <p>{{title}}</p>
        </div>
    </div>
</script>

样式

body {
  margin: 0;
  padding: 0;
  text-align: center;
}

.slide {
  width: 300px;
  padding: 20px;
  margin: 10px auto 10px auto;
  height: 250px;
  background: #f6f6ed;
  position: relative;
  text-align: center;
}

.slide p {
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: sans-serif;
}

.slide .img {
  max-width: 100%;
  max-height: 210px;
  text-align: center;
  opacity: 1;
  display: inline;
  -webkit-transition: opacity 0.25s ease-in-out;
  -moz-transition: opacity 0.25s ease-in-out;
  -o-transition: opacity 0.25s ease-in-out;
  transition: opacity 0.25s ease-in-out;
}

.imgholder {
  width: 100%;
  text-align: center;
}

无限滚动脚本

function handleScroll(e) {
    if(window.scrollY + window.innerHeight + 1000 > document.body.offsetHeight) {
        fetchBirds();//请求数据
    }
    handleDefer();  //判断是否可见
} 
window.addEventListener('scroll', handleScroll);

获取包含很多图片的内容时,当他们被插入到页面中是,浏览器就开始获取图像,这意味着同时下载,浏览器的下载通道被占满,使用户看的图片显示更慢,同时,由于内容先于用户加载,可能下载永远无法被看到的图像,在这里可以使用延迟加载,当图像被看到时才下载加载图像,使页面更快,还可以节省用户的流量。

延迟加载图像

function isVisible(node) {//判断是否可见
    //get the dimensions we need
    var scrollTop = window.scrollY,
        offTop = node.offsetTop,
        offsetHeight = node.offsetHeight,
        innerHeight = window.innerHeight,
        topViewPort = scrollTop,
        bottomViewPort = scrollTop + innerHeight;

    //figure out if it is in the viewport or not
    return offTop + offsetHeight > topViewPort && offTop < bottomViewPort;
}

function handleDefer() {//可见就加载图片
    //find all the slides, I'm fetching the container
    //rather than the image because I don't know the image
    //heights yet
    var list = document.querySelectorAll('.slide');
    for (var i=0, len = list.length; i < len; i++) {
        thisImg = list[i].querySelector('.img');
        if(thisImg.src) {
            continue;
        }
        //if they are visible, update the src
        if(isVisible(list[i])) {
            var src = thisImg.getAttribute('data-src');
            if(src) {
                thisImg.src = src;
                thisImg.removeAttribute('data-src');
            }

        }
    }
}

现在图像使延迟加载的,但加载时会看到图像空白,体验并不是很好,我们可以加上动画效果并优化延迟加载效果

.slide .img{
 transition:opacity .25s ease-in-out;
}
function handleDefer() {
    console.time('defer');
    var i, list, thisImg, deferSrc, img, handler,

    //the slide cache is populated by the function that
    //loads the data so that the defer code doesn't need
    //to keep querying the dom.
    list = slideCache, 
    len = listLength;


    for (i=0; i < len; i++) {
        thisImg = list[i].img
        var deferSrc = list[i].src;
        if(isVisible(list[i].id)) {

            //create a closure for for simple preload stuff
            handler = function() {
                var node, src;
                node = thisImg;
                src = deferSrc;

                return function () {
                    node.src = src;
                    node.style.opacity = 1;
                    loaded[deferSrc] = true;
                }
            }();
            //申明一个image,然后将src赋给改image的src,等待图像下载完成后再讲路径替换(此时图像已经下载到本地了,并使用动画效果显示)
            var img = new Image();
            img.onload = handler;
            img.src = list[i].src;

        }
    }
    console.timeEnd('defer');
}

现在加上了动画效果,在感知的性能上的提升是显著的。
可能你已经注意到了,我们是从slideCache而不是从DOM得到的幻灯片信息,这是应用了“只写入DOM”策略。DOM只有在添加新内容时才会被修改。数据会使用updateSlideCache函数来缓存。

var slideCache;

function updateSlideCache(node) { //在插入数据时调用此函数
    var list = node.querySelectorAll('.slide'),
        len = list.length
        obj;

    slideCache = [];

    for (var i=0; i < len; i++) {
        obj = {
            node:list[i],
            id:list[i].getAttribute('data-id'),
            img:list[i].querySelector('.img')
        }

        obj.src = obj.img.getAttribute('data-src');
        slideCache.push(obj);
    }
}

这里的node是一个只包含新添加的数据的节点。

另一个减低速度的是isVisible()函数, isVisible()函数需要大量的DOM读取和检查来执行它的运算。
使用缓存来快速检查元素的可见性

var slideMap = {};

//to simplify look up this now takes a photo id,
//which is the same as a slide id.
function isVisible(id) {

    var offTop, offsetHeight, data;

    //if the slide is cached we can get the
    //values from there
    if(slideMap[id]){
        offTop = slideMap[id].offTop;
        offsetHeight = slideMap[id].offsetHeight;

    //if the slide is not cached, update the cache
    }else {
        node = document.getElementById('s-' + id);
        offsetHeight = parseInt(node.offsetHeight);
        offTop = parseInt(node.offsetTop);
        data = {
            node:node,
            offTop:offTop,
            offsetHeight:offsetHeight
        };

        slideMap[id] = data;
    }

    //in the cached case this is just math, no DOM inspection at all
    if(offTop + offsetHeight > topViewPort && offTop < bottomViewPort) { 
        return true;
    } else {
        return false;
    }
}
 《HTML5触摸界面设计开发》专注于触摸界面的开发,内容的结构和优化网站的思路大概一致。上半部分涵盖了能使各类网站,特别是移动网站变快的基本概念。第2章和第3章告诉你如何创建一个简单的网站,并能快速加载。第4章可以帮助你使用缓存来提高用户再次访问时的速度。第5章是关于要摒弃一次性的页面加载方式和重构应用程序以使实际上和感觉到的性能都达到最优的。书的后半部分是专门讲触摸界面的,特别是尽可能地让它们更平稳和快速。   《HTML5触摸界面设计开发》适合具有一定经验的Web开发者阅读参考。 目录 第1章 移动设备概述 0 1.1 触摸设备和桌面设备之间的差异 2 1.2 广泛使用的设备 3 1.3 HTML 56 1.4 神秘谷,是什么让触摸界面反应灵敏? 7 1.5 总结 9 第2章 创建一个简单的内容型网站 10 2.1 选择一个观念:移动优先或置后 12 2.2 创建标记 13 2.3 奠定基础的标签 15 2.4 理解 Viewport 15 2.5 响应式的CSS 19 2.6 总结 24 第3章 提高第一次加载的速度 25 3.1 浏览器是如何加载页面的 27 3.2 为什么页面加载缓慢? 27 3.3 用YSlow和PageSpeed提升速度 30 3.4 解决常见的问题 33 3.5 将它们全部放在一起 41 3.6 总结 41 第4章 加快下一次访问的速度 42 4.1 在HTTP中缓存 44 4.2 为移动优化45 4.3 使用网络存储(Web Storage) 46 4.4 应用缓存(Application Cache) 53 4.5 总结 57 第5章 使用PJAX提升触摸体验 58 5.1 页面加载的代价 60 5.2 浏览器历史API 62 5.3 添加PJAX 69 5.4 总结 77 第6章 轻触VS单击:基本的事件处理 78 6.1 是什么让轻触不同? 80 6.2 触摸事件简介 80 6.3 处理轻触 83 6.4 总结 89 6.5 项目 89 第7章 CSS过渡、动画和变换 90 7.1 动画元素 92 7.2 CSS变换 105 7.3 总结 112 7.4 项目 112 第8章 JavaScript性能最优化 113 8.1 性能测试和调试 115 8.2 只写入DOM 116 8.3 给用户反馈的优先级是最高的 117 8.4 将它们一起使用:无限滚动 118 8.5 总结 127 8.6 项目 127 第9章 手势的基本内容 128 9.1 为什么用手势呢? 130 9.2 创建一个循序渐进增强的触摸控制 131 9.3 创建一个触摸控制的灯箱(lightbox) 136 9.4 总结 150 9.5 项目 150 第10章 滚动与滑动 151 10.1 滚动 153 10.2 布局失效 159 10.3 让鸟类浏览工具可滑动 161 10.4 总结 176 10.5 项目 177 第11章 双指缩放和其他复杂的手势 178 11.1 了解多点触摸的限制和支持情况 180 11.2 处理多点触摸 180 11.3 处理双指缩放 185 11.4 总结 195 11.5 项目 195
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值