Android禁用webview载入数据

咨询做安卓的同学,总得来说就两条:
webView.getSettings().setBlockNetworkImage(true);
webView.getSettings().setBlockNetworkLoads(true);
两条的功能就是阻塞对应类型的加载
如果要禁用就是true;
如果要启用就是false。
阻塞应该是为了加载速度快和安全着想。
实战中碰到的问题就是,wap端调用客户端的方法,客户端默认在方法回调结束后阻塞了加载,导致回调后再也无法请求ajax,使目标交互无法执行。
所以要根据实际情况选择是否阻塞。

seajs使用时出现的问题累积

加载jquery引用后出现报错

问题:
用正常的方法加载,jquery也确实载入到页面中了,但是引用的时候却说Object not defind。

解决:
引用的id要和jquery里面defind中的值互相对应才可以正常使用。

2.0版本取消了data-config和data-main的属性使用

问题:

解决:
按照常规的方式去引用配置文件和main初始化文件

浏览器缓存机制简介

这篇文章主要简单介绍浏览器缓存的机制,我们在做Server端响应时间优化的时候经常会接触到缓存的概念,例如经常会用到Memcached或Redis。我曾经使用缓存将原本一分钟才能获取的数据优化到了不到一秒的时间,当然,缓存也不是万能的,某些数据可以使用缓存或者必须使用缓存,有些数据则必须禁用掉缓存,确保每次请求返回的都是最新的数据,技术的运用方式是建立在业务的需求上的。

浏览器有一套自己的缓存机制,而在这个机制的基础上缓存规则的制定则主要依靠后端来实现,这属于一个合格的WEB开发者必须了解的内容。下文中提到的缓存概念,如果没有特殊说明都是指浏览器缓存,本文主要使用Chrome作为客户端,同时对Chrome开发者工具的一些细节进行了介绍。

什么是缓存?

引用Wikipedia上对Web cache的介绍,缓存就是:

A web cache is a mechanism for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag.

翻一下大意是:

WEB缓存就是临时存储WEB文档,例如HTML页面、图片等降低带宽使用、服务器负载、提升响应速度的一种机制。
我们使用的任何一个现代浏览器都支持缓存机制。

缓存在哪里?

IE浏览器:

我们可以通过IE的设置界面来查看缓存存放的位置:Internet选项->点击常规选项卡设置按钮->点击查看文件按钮即可自动打开缓存目录。如下图:

enter image description here

Firfox

查看Firefox浏览器缓存可以在Firefox地址栏输入about:cache来查看缓存详情,如图:

enter image description here

Chrome

Chrome并没有直接说明缓存目录、大小等具体信息,不过我们可以用Google查到,以Windows平台为例,Chrome的缓存目录在C:\Users\{{user name}}\AppData\Local\Google\Chrome\User Data\Default\Cache目录下。

Chrome Dev Tools NetWork简单介绍

首先我们对Chrome Dev Tools的NetWork功能做下简单的介绍。

当我们的浏览器向服务器发送请求时会携带一些基本的信息,如User-Agent、Cookie等,我们可以使用浏览器自带的开发者工具看到,如下:

// request header
GET /jquery.autocompleteV2.js HTTP/1.1
Host: 192.168.33.10
Connection: keep-alive
Cache-Control: max-age=0
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
DNT: 1
Referer: http://192.168.33.10/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2
Cookie: cmTPSet=Y; ylCookie=ylCookie; tma=86847064.57393759.1402022771631.1402022771631.1402022771631.1; tmd=6.86847064.57393759.1402022771631.
服务器根据请求返回响应(response),响应头信息,如下:

// response header
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Sat, 07 Jun 2014 13:32:29 GMT
Content-Type: application/x-javascript
Last-Modified: Sat, 07 Jun 2014 07:21:44 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Content-Encoding: gzip
下图是Chrome Dev Tools下的网络请求的概览:

chrome_http_request_list

网络概览列表的Size Content栏,上边的数值Size表示响应大小,Size大小 = Content大小 + 响应头大小, Content表示响应内容实际大小,比如浏览器请求了一个实际尺寸为61093字节的文件,那么这里Content的值便为61093byte ÷ 1024 ≈ 59.7KB,Size值不一定大于Content的值,当我们在开启Gzip压缩的情况下Size的大小很可能小于Content的大小,开启Gzip后,尽管服务器没有直接告诉我们响应内容的Content-Length大小,但是浏览器拿到压缩后的响应内容是可以间接的反向计算出响应内容的原始大小的,还有一种情况是Content使用的是本地缓存,也就是服务器返回304状态码告诉浏览器继续使用缓存中的内容,Size的大小只是响应头的大小,Content大小为从缓存中读取的响应内容的大小。
当我们的光标移动到HTTP请求的timeline上时会显示网络请求时间花费的详细信息,如图:

http_timeline

这里涉及到几个名词,下面解释下Chrome NetWork Timeline状态名词的意义:

Blocking代表了等待当前已存在连接可用状态所花费的时间,相当于我们将请求A放入浏览器请求队列里面,浏览器依次处理队列里面的请求直到开始处理请求A所花费的等待时间。
Proxy代表了连接代理服务器所花费的时间。
DNSLookup代表了DNS查找花费的时间。
Connecting代表了创建连接所花费的时间,包括TCP连接建立、DNS查找、连接代理服务器与创建安全连接(SSL)所花费的时间总和。
Sending代表了发送请求数据所花费的时间。
Waiting代表了等待服务器响应所花费的时间。
Receiving代表了接收服务器响应内容花费的时间。
所以这里的Time Latency一栏Time代表了从我们创建请求到浏览器接收到服务器响应内容这个过程所花费的时间,Latency代表了从我们创建请求到服务器生成响应内容这段时间花费的时间。

缓存是如何工作的

更改Nginx配置,对所有js和css文件设置一套有效期为30天的缓存规则,Nginx站点配置添加代码:

location ~* \.(css|js)$ {
expires 30d;
}
重启Nginx服务使配置生效,清空浏览器缓存,模拟首次访问页面,刷新(请点击浏览器工具栏刷新按钮或使用右键菜单刷新功能刷新)页面。这时响应头会多出两个字段的数据:Cache-Control:和Expires,响应头变为了:

// response header
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Sat, 07 Jun 2014 13:47:27 GMT
Content-Type: application/x-javascript
Last-Modified: Sat, 07 Jun 2014 07:21:44 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Mon, 07 Jul 2014 13:47:27 GMT
Cache-Control: max-age=2592000
Content-Encoding: gzip
Cache-Control: max-age=259200表示缓存将在该页面请求后的259200秒后过期。
Expires: Mon, 07 Jul 2014 13:47:27 GMT表示缓存将在2014年7月7号 13:47:27后过期,注意:使用Expires指定过期时间,如果服务器时间和客户端时间不一致(这个问题很常见,在写这篇博客时,我的Ubuntu服务器时间比标准时间慢了4分钟),这时候通过Expires指定过期时间将达不到我们预期的效果,幸运的是绝大多数浏览器(IE6.0都支持HTTP1.1,还用怕什么?)和HTTP Server都已经支持HTTP/1.1,所以当响应头同时有Expires和Cache-Control时浏览器会优先考虑Cache-Control。

那在缓存期有效的这段时间刷新页面浏览器是如何使用已缓存的内容的呢?好,再次刷新(刷新方式同上)浏览器,服务器返回了304的status code,请求头变为了:

// request header
GET /jquery.autocompleteV2.js HTTP/1.1
Host: 192.168.33.10
Connection: keep-alive
Cache-Control: max-age=0
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
DNT: 1
Referer: http://192.168.33.10/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2
Cookie: cmTPSet=Y; ylCookie=ylCookie; tma=86847064.57393759.1402022771631.1402022771631.1402022771631.1; tmd=6.86847064.57393759.1402022771631.
If-Modified-Since: Sat, 07 Jun 2014 07:21:44 GMT
注意这里多了个If-Modified-Since字段,该值就是第一次响应头返回的Last-Modified字段,当服务器收到浏览器发送来的请求头时根据该字段判断是否让浏览器使用缓存内容,若在Last-Modified指定的时间后文件发生了变化服务器返回的status code变为200,同时会将最新的响应内容发送给浏览器,就像我们首次请求一样。如果在Last-Modified指定的时间后文件没有发生变化,服务器将返回status code变为304告诉浏览器:“你可以继续使用之前缓存的内容”,响应头变为:

// response header
HTTP/1.1 304 Not Modified
Server: nginx/1.1.19
Date: Sat, 07 Jun 2014 14:01:50 GMT
Last-Modified: Sat, 07 Jun 2014 07:21:44 GMT
Connection: keep-alive
Expires: Mon, 07 Jul 2014 14:01:50 GMT
Cache-Control: max-age=2592000
如果这段时间请求的文件内容发生了变化,服务器返回的status code变为200,同时响应内容为请求资源的最新副本,响应头内容变为:

HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Sat, 07 Jun 2014 14:03:00 GMT
Content-Type: application/x-javascript
Last-Modified: Sat, 07 Jun 2014 14:02:56 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Mon, 07 Jul 2014 14:03:00 GMT
Cache-Control: max-age=2592000
Content-Encoding: gzip
当超出缓存有效期时,再次刷新页面,浏览器与服务器之间请求的协商过程也会验证请求资源是否被修改过,如果没有被修改缓存还是继续有效的,如果请求资源被修改过服务器将重新将请求资源的最新副本发送给浏览器。

页面刷新方式的区别

前面在演示时我们说到用指定的方式去刷新页面,那不同的刷新方式对于缓存会有什么效果呢?

一般常用有四种方式加载页面:

第一次请求时

首次请求初始化缓存机制,无特殊情况。

强制请求

强制请求一般是按下Ctrl + F5组合键来实现,强制刷新时浏览器会忽略一切缓存机制,告诉服务器“把最新的内容给我”,就像我们第一次打开这个页面一样。

一般刷新

常用的一般刷新方法有按下F5键或者在浏览器右键弹出菜单中刷新页面,这时浏览器与服务器之间将按照之前协商好的缓存协议进行对话。

点击浏览器转到按钮

通过浏览器地址栏转到一个已经打开过的页面浏览器将根据已缓存的请求资源是否已经过期来判断是否和服务器进行对话,如果缓存没有过期浏览器直接从缓存中读取数据作为响应内容,浏览器不会与服务器进行对话,不会发送任何的HTTP请求。

更详细的请参考下面的链接:

What requests do browsers’ “F5” and “Ctrl + F5” refreshes generate?
Behind Refresh Button
如何有效的控制缓存?

前面我们说过,当通过地址栏跳转到一个已经访问过的页面时,如果在之前设置的缓存有效期之内浏览器将不会与服务器进行任何协商直接读取本地缓存内容作为响应内容,那即使我更新了一段css代码,那么老访客看到的可能还是从本地读取的老旧的样式表文件,那怎么样才能让我更新的内容强制让客户端与服务器进行对话确认呢?简单:最常见的办法是在文件路径后面添加指定版本号,例如:

每次对文件的修改都要更新版本号,通过这种方式强制让浏览器与服务器进行对话,解决缓存的负面问题。

缓存的意义

合理的设置客户端端缓存可以最大限度的节省服务器网络流量开销、减轻服务器负载、提升用户体验等。

 

原文地址>>

手机拖动时js停止运行,倒计时实例

问题描述

 

在手机中拖动手机屏幕(window的scroll事件)或关闭手机屏幕时,会让js暂停运行。

这个状况会直接导致类似倒计时这样的效果出现问题。

比如你做了个页面上的倒计时,按照秒的精度倒数,当你拖动屏幕浏览内容时只要你的手没有放开,那时间是不动的。(可以联想到类似轨迹动画也是会停止的)。

 

我的解决办法

一、改变拖动的方式。

将scroll事件改为touchMove,可以让你在拖动的时候仍然保持js的运行。
典型的插件iscroll,虽然这个插件还不是完全体,有一些已知的bug,但是可以给你一个思路让你解决问题。

这个只能解决拖动上得问题,关闭手机屏幕还是无解的。

 

二、利用机器时间差异

这个算是曲线救国(谢谢数学老师),做一个setInterval来循环调用机器时间(间隔事件根据需要设定),如果与上次的调用时间超出预计,那就是产生了拖动和灭屏的状况,那么我们根据这个时间差,来计算目标时间应该达到的目标状态,并重置到这个状态。
我觉得是个代价相对较小的方法。

 

假设刚进入页面的时间是准确的
已知服务器时间 x 和当前机器时间 y
因为服务器时间和机器时间不一定相等
所以我们假定这个时间差z = x-y;
z为恒定值
获取当前机器时间的代码代价较小,我们可以在定时器中一直获取动态的y,再根据z,校准当前的确定的服务器时间,而不用反复请求。
如果是倒计时,需要的是时间差
那就需要一个目标时间a
时间差b的校准公式应该是
b= a-y-z;

 

三、面对鬼畜产品经理

“我要拖动的时候时间是动的,灭屏回来时间也是对的!”
这个时候结合方法一和二,就可以解决了。
我比较懒,方法在上面,自己写一写…
“什么?灭屏回来会卡顿?”
Sorry…

关于input的radio和checkBox组件的一些用法总结

最近用的比较多,在这里总结一下。
要注意的是我下面的东西主要是在移动端开发测试的,chrome也测试了,pc端其他浏览器我会在之后补上说明的。
我这里说的click是已经优化过的点击,自己在合适的时候切换成touch。
另外,无视jquery2+。

大家都知道的

在input外面加上label,或者通过label中的for属性指向input,可以通过点击label区域触发input的change或者focus。
针对radio和checkBox主要就是change事件。
那么触发input:radio和input:checkBox会有什么操作呢?
radio:如果已选中,不会有变化。如果未选中,那么在同一个name里面,选中该radio,原来选中的radio取消选中。
checkBox: 如果已选中,取消选中;如果未选中,改变为选中状态。

你可能不知道的

前提:
这里以jquery的语法描述。
不在html中直接操作checked属性,因为要做遍历。

先说radio:
我们要通过label间接改变一个radio组的状态可以用click事件,也可以用change事件
以$(this).find(“input:radio”).is(‘:checked’)来判断当前的子元素是不是选中状态。
以$(this).find(“input:radio”).get(0).checked = false;来取消选中状态(如果你默认一个都不选中有可能会用到这个)。
click与change的区别就是,不管你该元素的状态是否变化,click都会触发。
而change只有在你元素选中与否变化时才会触发。所以我认为change是优选。
而你想通过其他方式修改这组单选状态的时候,可以通过$(this).find(“input:radio”).eq(index).trigger(“click”)来实现,不能用change。

以上的操作在pc端是没问题的,但是在移动端,想用change操作input的属性是不可以的。
那checkBox呢:
从上面对radio和radio其实没有不同。
但在做特别样式的展示,并且要把丑陋的input隐藏时,要注意保持展示和看不到的input状态是一致的。
我开始用click测试的时候就发现展示状态改变正常,但是input可能没有变化~

总结一些用法

如何确定该选择项目是否被选中:
有人说我要用$(this).attr(“checked”)来查看当前状态,那在我上面说的这个方发现,这么判断永远是空…
用$(this).is(‘:checked’)可以达到判断是否选中。当然你愿意用class标记是否选中也可以。
change和click:
pc端用change提高效率,移动端用click。

综合实例说事

点击查看实例 >>
或者扫码。

一款滚动条插件mCustomScrollbar

考虑到之前自己写的那个功能有欠缺,比如我的只是纵向滚动,这次在自己更新jscroll之余也找到了一个比较完善的插件mCustomScrollbar。

 

mCustomScrollbar

官网:http://manos.malihu.gr/jquery-custom-content-scroller/
github:https://github.com/malihu/malihu-custom-scrollbar-plugin
插件的demo很详细,如果你觉得插件有点大,可以自己优化一下去掉不想要的功能。
注意这类滚动条的插件都要在你的目标元素显示在画布时(能读取到长宽的时候),才能正确渲染,不然你就要自己定宽高了。
我在最近的一个项目中用了它,涉及到一个初始化时内容区域要滚动条从end点开始,并且是横向的。
看代码:
$(".scroll").mCustomScrollbar({
horizontalScroll:true,//横向滚动
scrollButtons:{//是否要左右的箭头按钮
enable:true
},
scrollInertia : 20//滚动的缓动速度
}).mCustomScrollbar("scrollTo","right");//跳到最右

这里注意如果不把scrollInertia设置的低一点,载入的时候会有从左滚到右的动画,最近很懒,就选择了这个比较简单的方案。

一段以userAgent判断是否为手机浏览器的js代码

虽然我不关心,但同事说腾讯是这么用的。
其实就是写了个正则字典穷举手机的可能。个人感觉适用性能覆盖90%以上的用户(只要“安全”浏览器不把userAgent改的太奇葩,或者用户不太奇葩)。
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
if(window.location.href.indexOf("?mobile")<0){
try{
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
//移动端
}else if(/iPad/i.test(navigator.userAgent)){
//这里对ipad做了处理
}else{
//移动端
}
}catch(e){}
}
}else{
//pc端
}

wp是个特殊的存在(IE),要怎么单独判断wp呢。
var ISWP = !!(navigator.userAgent.match(/Windows\sPhone/i));
因为wp的特殊性海量的方法给你判断,具体情况再具体分析。