JavaScript高级程序设计(第3版)学习笔记 第25章

第25章 新兴的API

1.无论是使用setInterval()还是 setTimeout()制作动画都不十分精确,这两个实际上只是指定了把动画代码添加到浏览器 UI 线程队列中以等待执行的时间。

为了保证动画平滑,Mozilla提出了mozRequestAnimationFrame()方法,Chrome 提出了webkit- RequestAnimationFrame()方法,IE10+提出了msRequestAnimationFrame()方法。那么可以在 Firefox 4+、IE10+和 Chrome 中可以参考以下模式创建动画循环。

(function(){
    function draw(timestamp){
        //计算两次重绘的时间间隔
        var drawStart = (timestamp || Date.now()),
            diff = drawStart - startTime; 

        //使用 diff 确定下一步的绘制时间

        //把 startTime 重写为这一次的绘制时间 
        startTime = drawStart;

        //重绘 UI
        requestAnimationFrame(draw);
    }
    var requestAnimationFrame = window.requestAnimationFrame ||
                                window.mozRequestAnimationFrame ||
                                window.webkitRequestAnimationFrame ||
                                window.msRequestAnimationFrame,
        startTime = window.mozAnimationStartTime || Date.now();
    requestAnimationFrame(draw);
})();

2.Page Visibility API(页面可见性 API):让开发人员知道页面是否对用户可见,由以下三部分组成:

  • document.hidden:表示页面是否隐藏的布尔值。页面隐藏包括页面在后台标签页中或者浏览器最小化。
  • document.visibilityState:有下列 4 个可能状态的值:
  1. 页面在后台标签页中或浏览器最小化。
  2. 页面在前台标签页中。
  3. 实际的页面已经隐藏,但用户可以看到页面的预览(就像在 Windows 7 中,用户把鼠标移动到任务栏的图标上,就可以显示浏览器中当前页面的预览)。
  4. 页面在屏幕外执行预渲染处理。
  • visibilitychange 事件:当文档从可见变为不可见或从不可见变为可见时,触发该事件。
  • //检查浏览器是否支持API
    function isHiddenSupported(){
            return ("hidden" in document || "msHidden" in document || "webkitHidden" in document);
      }
    
    //在IE和Chrome 中侦听visibilitychange 事件,IE 中,叫 msvisibilitychange,在 Chrome 中叫 webkitvisibilitychange。
    function handleVisibilityChange(){
        var output = document.getElementById("output"),
            msg;
        if (document.hidden || document.msHidden || document.webkitHidden){ 
            msg = "Page is now hidden. " + (new Date()) + "<br>";
        } else {
            msg = "Page is now visible. " + (new Date()) + "<br>";
        }
    
        output.innerHTML += msg;
    }
    
    //要为两个事件都指定事件处理程序
    EventUtil.addHandler(document, "msvisibilitychange", handleVisibilityChange); EventUtil.addHandler(document, "webkitvisibilitychange", handleVisibilityChange);

3.Geolocation API的实现是 navigator.geolocation 对象,包含 3 个方法:

getCurrentPosition():触发请求用户共享地理定位信息的对话框,接收 3 个参数:成功回调函数、可选的失败回调函数和可选的选项对象。

  • 成功回调函数,接收到一个 Position 对象,有两个属性:coords 和 timestamp
    coords 包含下列与位置相关的信息:
    latitude:以十进制度数表示的纬度。
    longitude:以十进制度数表示的经度。
    accuracy:经、纬度坐标的精度,以米为单位。
  • 失败回调函数,接收到一个对象。有两个属性:message 和 code。
    message :保存着给人看的文本消息,解释为什么会出错。
    code :保存着一个数值,表示错误的类 型:用户拒绝共享(1)、位置无效(2)或者超时(3)。
  • 选项对象,用于设定信息的类型。可以设置的选项有三个:
    enableHighAccuracy :一个布尔值,表示必须尽可能使用最准确的位置信息。
    timeout :以毫秒数表示的等待位置信息的最长时间。
    maximumAge :上一次取得的坐标信息的有效时间,以毫秒表示,如果时间到则重新取得新坐标信息。 
navigator.geolocation.getCurrentPosition(function(position){             
    drawMapCenteredAt(position.coords.latitude, positions.coords.longitude);
}, function(error){
    console.log("Error code: " + error.code); 
    console.log("Error message: " + error.message);
    }, {
        enableHighAccuracy: true,
        timeout: 5000,
        maximumAge: 25000
});

watchPosition():接收的参数 与 getCurrentPosition()方 法 完 全 相 同 。与 定 时 调 用 getCurrentPosition()的效果相同。在第一次调用 watchPosition()方法后,会取得当前位置,执行成功回调或者错误回调。然后,watchPosition()就地等待系统发出位置已改变的信号(它不会自己轮询位置)。调用 watchPosition()会返回一个数值标识符,用于跟踪监控的操作。

clearWatch():取消了监控操作。

var watchId = navigator.geolocation.watchPosition(function(position){                                                                         drawMapCenteredAt(position.coords.latitude, positions.coords.longitude);
}, function(error){
    console.log("Error code: " + error.code); 
    console.log("Error message: " + error.message);
});

clearWatch(watchId);

4.File API:可以读取文件内容,用于显示、处理和上传。与 HTML5 的拖放功能结合,很容易就能创造出拖放上传功能。

(1)在通过文件输入字段选择了一或多个文件时,files 集合中将包含一组 File 对象,每个 File 对象对应着一个文件。每个 File 对象都有下列只读属性:

  • name:本地文件系统中的文件名。
  • size:文件的字节大小。
  • type:字符串,文件的 MIME 类型。
  • lastModifiedDate:字符串,文件上一次被修改的时间。
  • //通过侦听 change 事件并读取 files 集合知道选择的每个文件的信息
    var filesList = document.getElementById("files-list");
    EventUtil.addHandler(filesList, "change", function(event){
        var files = EventUtil.getTarget(event).files,
                    i = 0,
                    len = files.length;
    
        while (i < len){
            console.log(files[i].name + " (" + files[i].type + ", " + files[i].size +"     bytes) ");
            i++; }
    });

(2)FileReader 类型实现一种异步文件读取机制,提供了如下 几个方法:

  • readAsText(file,encoding):以纯文本形式读取文件,将读取到的文本保存在 result 属 性中。第二个参数用于指定编码类型,是可选的。
  • readAsDataURL(file):读取文件并将文件以数据 URI 的形式保存在 result 属性中。
  • readAsBinaryString(file):读取文件并将一个字符串保存在result属性中,字符串中的每个字符表示一字节。 、
  • readAsArrayBuffer(file):读取文件并将一个包含文件内容的 ArrayBuffer 保存在result 属性中。

还提供了三个最有用的事件:

  • progress事件:每过 50ms 左右,就会触发,通过事件对象可以属):lengthComputable、loaded 和 total。
  • error 事件:由于种种原因无法读取文件,就会触发 ,触发时,相关的信息将保存到 FileReader 的 error 属性中,保存一个对象,该对象只有一个属性 code,即错误码。 这个错误码是 1 表示未找到文件,是 2 表示安全性错误,是 3 表示读取中断,是 4 表示文件不可读,是 5 表示编码错误。
  • load 事件:文件成功加载后会触发
  • var filesList = document.getElementById("files-list");
    EventUtil.addHandler(filesList, "change", function(event){
        var info = "",
            output = document.getElementById("output"),
            progress = document.getElementById("progress"),
            files = EventUtil.getTarget(event).files,
            type = "default",
            reader = new FileReader();
        if (/image/.test(files[0].type)){
            reader.readAsDataURL(files[0]);
            type = "image";
        } else {
            reader.readAsText(files[0]);
            type = "text";
        }
        reader.onerror = function(){
            output.innerHTML = "Could not read file, error code is " +
                                reader.error.code;
        }; 
        reader.onprogress = function(event){
            if (event.lengthComputable){
                    progress.innerHTML = event.loaded + "/" + event.total;
            }
        };
        reader.onload = function(){
            var html = ""; 20
    
            switch(type){
                case "image":
                    html = "<img src=\"" + reader.result + "\">";
                    break;
                case "text":
                    html = reader.result;
                    break; 
            }
            output.innerHTML = html;
        };
    });
    

(3)slice()方法读取部分内容,接收两个参数:起始字节及要读取的字节数,返回一 个 Blob 的实例,Blob 是 File 类型的父类型。

//跨浏览器的blobSlice函数
function blobSlice(blob, startByte, length){
    if (blob.slice){
        return blob.slice(startByte, length);
    } else if (blob.webkitSlice){
        return blob.webkitSlice(startByte, length);
    } else if (blob.mozSlice){
        return blob.mozSlice(startByte, length);
    } else {
        return null;
    }
}

(4) 使用对象 URL (被称为 blob URL,指的是引用保存在 File 或 Blob 中数据的 URL)可以不必把文件内容读取到 JavaScript 中而直接使用文件内容。

//创建对象 URL函数,消除不同浏览器的命名差异,返回值是一个字符串,指向一块内存的地址
function createObjectURL(blob){
    if (window.URL){
        return window.URL.createObjectURL(blob);
    } else if (window.webkitURL){
        return window.webkitURL.createObjectURL(blob);
    } else {
        return null;
    }
}

/*直接把对象 URL 放在<img>标签中,省去了把数据先读到 JavaScript 中的麻烦。
<img> 标签会找到相应的内存地址,直接读取数据并将图像显示在页面中。*/
var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList, "change", function(event){
    var info = "",
        output = document.getElementById("output"), 
        progress = document.getElementById("progress"), 
        files = EventUtil.getTarget(event).files, 
        reader = new FileReader(),
        url = createObjectURL(files[0]);
        if (url){
            if (/image/.test(files[0].type)){
                output.innerHTML = "<img src=\"" + url + "\">";
            } else {
                output.innerHTML = "Not an image.";
            }
        } else {
            output.innerHTML = "Your browser doesn't support object URLs.";
        }
});

//最好在不需要某个对象 URL 时,就马上手工释放其占用的内存,消除不同浏览器的命名差异
function revokeObjectURL(url){
    if (window.URL){
        window.URL.revokeObjectURL(url);
    } else if (window.webkitURL){
        window.webkitURL.revokeObjectURL(url);
    }
}

(5)结合使用 HTML5 拖放 API 和文件 API,将放置到页面中自定义的放置目标中的文件信息显示出来

var droptarget = document.getElementById( "droptarget");
    function handleEvent(event){
        var info = "",
            output = document.getElementById("output"),
            files, i, len;
        EventUtil.preventDefault(event);//取消拖放的默认行为

        if (event.type == "drop"){
            //通过event.dataTransfer.files读取文件信息
            files = event.dataTransfer.files;
            i = 0;
            len = files.length;

            while (i < len){
                info += files[i].name + " (" + files[i].type + ", " +     files[i].size+" bytes)<br>";
            i++;
}
        output.innerHTML = info;
    }
}

EventUtil.addHandler(droptarget, "dragenter", handleEvent); EventUtil.addHandler(droptarget, "dragover", handleEvent); EventUtil.addHandler(droptarget, "drop", handleEvent);

 (6)通过 XHR 直接把文件上传到服务器

var droptarget = document.getElementById("droptarget");
function handleEvent(event){
    var info = "",
        output = document.getElementById("output"),
        data, xhr,
        files, i, len;

    EventUtil.preventDefault(event);

    if (event.type == "drop"){
        data = new FormData();//为了以表单提交的方式来上传文件,创建一个 FormData 对象
        files = event.dataTransfer.files;
        i = 0;
        len = files.length;

        while (i < len){
            data.append("file" + i, files[i]);//调用 append()方法并传入相应的 File 对象作为参数
            i++; 
        }
    
        xhr = new XMLHttpRequest();
        xhr.open("post", "FileAPIExample06Upload.php", true);
        xhr.onreadystatechange = function(){
            if (xhr.readyState == 4){
                alert(xhr.responseText);
            } 
        };
        xhr.send(data);//发送给服务器
    } 
}

EventUtil.addHandler(droptarget, "dragenter", handleEvent); EventUtil.addHandler(droptarget, "dragover", handleEvent); EventUtil.addHandler(droptarget, "drop", handleEvent);

5.Web Timing:给出了页面加载和渲染过程的很多信息,对性能优化非常有价值,核心是 window.performance 对象,有两个属性:

  • performance.navigation 属性也是一个对象,包含着与页面导航有关的多个属性。
  • performance.timing 属性也是一个对象,但这个对象的属性都是时间戳(从软件纪元开始经过的毫秒数),不同的事件会产生不同的时间值。

 6.Web Workers:可以运行异步 JavaScript 代码,避免阻塞用户界面。

  • 在执行复杂计算和数据处理的时候,非常有用;要不然,这些任务轻则会占用很长时间,重则会导致用户无法与页面交互。

(1)创建一个新的 Web Worker:实例化 Worker 对象并传入要执行的 JavaScript 文件名。

var worker = new Worker("stufftodo.js");

 (2)使用 postMessage()方法给 Worker 传递消息,可以随便传递任何形式的对象数据,Worker 接收到消息才会实际执行文件中的代码。

worker.postMessage(“start! ");
worker.postMessage({
     type: "command",
     message: "start! "
});

(3)Worker 是通过 message 和 error 事件与页面通信的,来自 Worker 的数据保存在 event.data 中。

 worker.onmessage = function(event){
    var data = event.data;
    //对数据进行处理 
}

(4)建议在使用 Web Workers 时,始终都要使用 onerror 事件处理程序,即使这个函数除了把错误记录到日志中什么也不做都可以。否则,Worker 就会在发生错误时,悄无声息地失败了。 error 事件对象中包含三个属性:filename(发生错误的文件名)、 lineno(代码行号) 和 message(完整的错误消息)。

worker.onerror = function(event){
    console.log("ERROR: " + event.filename + " (" + event.lineno + "): " + event.message);
};

(5)Web Worker 中的全局对象是 worker 对象本身,this 和 self 引用的都是 worker 对象,不能访问 DOM,也无法通过任何方式影响页面的外观 。当页面在 worker 对象上调用 postMessage()时,数据会以异步方式被传递给 worker,进而触发 worker 中的 message 事件。为了处理来自页面的数据,同样也需要创建一个 onmessage 事件处理程序。

//在页面中
var data = [23,4,7,9,2,14,6,651,87,41,7798,24],
    worker = new Worker("WebWorkerExample01.js");

    worker.onmessage = function(event){
        var data = event.data;
        //对排序后的数组进行操作 
};

//将数组发送给 worker 排序 
worker.postMessage(data);
//---------------------------------

//Web Worker 内部的代码 
self.onmessage = function(event){
    var data = event.data;
    //默认的 sort()方法只比较字符串 
    data.sort(function(a, b){
       return a – b;
    });
    self.postMessage(data);
};

//在 Worker 内部,调用 close()方法也可以停止工作
self.close();

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值