一个手机阅读器的WebApp

来源:互联网 发布:关闭miui优化会怎么样 编辑:程序博客网 时间:2024/04/27 19:11

按照惯例,咱也还是先上效果图。
有句名言说得好:没图说个脚本:)
iReader效果展示
还有一句名言叫做:talk is to easy, show me the code!
So 接下来咱们就开始看看这个小东西里面都有哪些重难点。

HTML页面部分

这部分还比较常规,没有特别需要注意或者说新颖的地方,有几个小tips看一下就好了。
* 因为作品是针对手机端的一个WebApp,所以为了让这个WebApp看起来更像是一个Native App,我们需要在页面部分的meta处声明以下代码,作用分别是:设备宽度等于视口宽度即使布局视口等于可视视口,这样布局视口就成为了理想视口;最小缩放1倍;最大缩放1倍;禁止用户缩放;

<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">

JS部分

一、第三方库的选择和使用
需要用到的第三方库有jQuery.base64.js、jQuery.jsonp.js,分别用来进行base64格式图片的获取以及jsonp的使用,此外在这里我是用了Zepto.js而不是jQuery作为前两个库的支持,这是因为在移动端的性能表现上,Zepto比jQuery稍微优秀一些,也正因如此在js文件引用时需要做那么一些小改动。

<script type="text/javascript" src="lib/zepto.min.js"></script><script type="text/javascript">    window.jQuery = $;</script><script type="text/javascript" src="js/jquery.base64.js"></script><script type="text/javascript" src="js/jquery.jsonp.js"></script><script type="text/javascript" src="js/index.js"></script>

一定要注意调用的顺序,zepto.js要最先调用。

知识拓展:jQuery与Zepto的异同

相同点:
Zepto最初是为移动端开发的库,是jQuery的轻量级替代品,因为它的API和jQuery相似,而文件更小。Zepto最大的优势是它的文件大小,只有8k多,是目前功能完备的库中最小的一个,尽管不大,Zepto所提供的工具足以满足开发程序的需要。大多数在jQuery中·常用的API和方法Zepto都有,Zepto中还有一些jQuery中没有的。另外,因为Zepto的API大部分都能和jQuery兼容,所以用起来极其容易,如果熟悉jQuery,就能很容易掌握Zepto。你可用同样的方式重用jQuery中的很多方法,也可以方面地把方法串在一起得到更简洁的代码,甚至不用看它的文档。
不同点:
* 针对移动端程序,Zepto有一些基本的触摸事件可以用来做触摸屏交互(tap事件、swipe事件),Zepto是不支持IE浏览器的,这不是Zepto的开发者Thomas Fucks在跨浏览器问题上犯了迷糊,而是经过了认真考虑后为了降低文件尺寸而做出的决定,就像jQuery的团队在2.0版中不再支持旧版的IE(6 7 8)一样。因为Zepto使用jQuery句法,所以它在文档中建议把jQuery作为IE上的后备库。那样程序仍能在IE中,而其他浏览器则能享受到Zepto在文件大小上的优势,然而它们两个的API不是完全兼容的,所以使用这种方法时一定要小心,并要做充分的测试。
* width()和height()的区别:Zepto由盒模型(box-sizing)决定,用.width()返回赋值的width,用.css(‘width’)返回加border等的结果;jQuery会忽略盒模型,始终返回内容区域的宽/高(不包含padding、border)。
* offset()的区别:Zepto返回{top,left,width,height};jQuery返回{width,height}。
* Zepto无法获取隐藏元素宽高,jQuery 可以。
* Zepto中没有为原型定义extend方法而jQuery有。
* Zepto的each方法只能遍历数组,不能遍历JSON对象。
* 事件委托差异:

var $doc = $(document);$doc.on('click', '.a', function () {    alert('a事件');    $(this).removeClass('a').addClass('b');});$doc.on('click', '.b', function () {    alert('b事件');});

在Zepto中,当a被点击后,依次弹出了内容为”a事件“和”b事件“,说明虽然事件委托在.a上可是却也触发了.b上的委托。但是在 jQuery 中只会触发.a上面的委托弹出”a事件“。Zepto中,document上所有的click委托事件都依次放入到一个队列中,点击的时候先看当前元素是不是.a,符合则执行,然后查看是不是.b,符合则执行。而在jQuery中,document上委托了2个click事件,点击后通过选择符进行匹配,执行相应元素的委托事件。
二、HTML5的本地存储
作品中的各项设置都是可以保存到本地,这样在下次登录刷新时会自动获取上次的设置。
这里主要是用了HTML5的LocalStorage

// 存储相关var prefix = 'iReader_';var StorageGetter = function(key) {    return localStorage.getItem(prefix + key);};var StorageSetter = function(key,value) {    return localStorage.setItem(prefix + key,value);};

知识拓展:HTML5的本地存储

本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。大小大概为5M。比Cookie的4KB好得多。
存储数据的方法就是给window.localStorage添加一个属性,属性都是以键值对的方式存在:

localStorage.a = 3;//设置a为"3"localStorage["a"] = "sfsf";//设置a为"sfsf",覆盖上面的值localStorage.setItem("b","isaac");//设置b为"isaac"var a1 = localStorage["a"];//获取a的值var a2 = localStorage.a;//获取a的值var b = localStorage.getItem("b");//获取b的值localStorage.removeItem("c");//清除c的值

推荐使用getItem()和setItem(),清除键值对使用removeItem(),一次性清除所有键值对使用clear()。此外还有key()方法在不知道有哪些键值的时候进行使用。
Note: HTML5本地存储只能存字符串,任何格式存储的时候都会被自动转为字符串,所以读取的时候,需要自己进行类型的转换。
三、跨刘浏览器的事件绑定
这里主要是因为有DOM0级、DOM2级以及IE事件存在导致的。

// 跨浏览器的事件绑定var addHandler = function(element, type, handler) {    if (element.addEventListener) {        element.addEventListener(type, handler, false);    }    else if (element.attachEvent) {        element.attachEvent("on"+type, handler);    }    else{        element["on"+type] = handler;    }};var getEvent = function(event) {    return event? event:window.event;};var getTarget = function(event) {    return event.target || event.srcElement;};

知识拓展(文本后面的PXXX代表内容位于JavaScript高级程序设计书中的页面)

DOM0级事件处理程序(最为传统的方式,至今仍都在支持):每个元素都有自己的事件处理程序属性,这些属性通常全部小写,例如onclick,将这些属性的值设置为一个函数,如btn.onclick=function(){};如要删除,则将值置为null,如btn.onclick=null
DOM2级事件处理程序:使用addEventListener()和removeEventListener()实现,接受三个参数:事件名(如click)、处理程序、布尔值(true为捕获阶段,false为冒泡阶段,通常为了兼容浏览器,使用false)。注:通过addEventListener()添加的匿名函数将无法移除。同一按钮添加多个事件,顺序执行
IE事件处理程序:使用attachEvent()和detachEvent()实现,接受两个参数:事件名(如onclick)、处理程序。同一添加多个事件,逆序执行。(p353)
DOM中(包括DOM0和DOM2)事件使用event、事件目标event.target、阻止默认行为preventDefault()方法(cancelable属性要为true)、取消事件捕获或者冒泡stopPropagation()
IE中事件使用window.event、事件目标window.event.srcElement、阻止默认行为returnValue=false、取消事件冒泡cancelBubble=true(p361)
四、从书城官网获取图书数据

// JSONPlet getJSONP = function(url,callback) {    return $.jsonp({        url:url,        cache:true,        callback:"duokan_fiction_chapter",        success:function(result) {            let data = $.base64.decode(result);            data = escape(data);            let json = decodeURIComponent(data);            //debugger;            callback(json);        }    });};

这里的图书信息是从多看书城的官网数据库通过jsonp的方式获取的,callback回调需设置为:duokan_fiction_chapter,这个是由多看书城制定的,不能修改。
此外拿到的数据需要对其进行base64的解码,然后通过escape()函数对字符串进行编码,这样就可以在所有的计算机上读取该字符串。最后使用decodeURIComponent()进行解码得到结果。

CSS部分

使用base64的格式来制作图标

.icon-font{    width: 20px;    height:13px;    background: url(data:image/png;base64,iVBORw0KGgoAAA94YlwCQTI3MEQiIHN0UmVmO/*后面太长省略*/    background-size:contain;

知识拓展

Data URL编码图片:通常在<img>标签中使用图片是采用src属性指定一个远程服务器上的资源。当页面加载时,浏览器会针对每个资源向服务器发送一个请求,一般浏览器并发请求数不能超过4个。因此大量使用会导致页面的加载延迟。
使用Data URL将图片以base64字符串的格式嵌入至src属性,则不会产生请求。(IE6/7不支持)
优势:当访问外部资源很麻烦或受限时、当图片是在服务器端用程序动态生成,每个访问用户显示的都不同时、当图片的体积太小,占用一个HTTP会话不是很值得时使用。
劣势:Base64编码的数据体积通常是原数据的体积4/3,也就是Data URL形式的图片会比二进制格式的图片体积大1/3;Data URL形式的图片不会被浏览器缓存,这意味着每次访问这样页面时都被下载一次。
如何避免劣势:在CSS中使用Data URL。通过CSS文件中的backround-image属性引用图片url地址:background-image: url(“data:XXX “);他避免了图片单独产生一次HTTP请求,又让图片随CSS被浏览器缓存(所有浏览器都很乐意缓存CSS文件)。
如何使用:在线Data URL生成工具、使用HTML5的FileReader()

var reader = new FileReader();//定义一个FileReadervar content;content = reader.readAsDataURL(localFile, "UTF-8");//readAS…完成后会将相对应的结果保存至result属性中,例如readAsDataURL、readAsText等,随后会调用onload或者onerror事件处理程序reader.onload = function(event) {    content = event.target.result;    document.getElementById("img").src = content;    document.getElementById("fileContent").value = content;    }reader.onerror = function(event) {      alert('error');    }}
原创粉丝点击