移动平台3G手机网站前端开发布局技巧汇总(转)

自Iphone和Android这两个牛逼的手机操作系统发布以来,在互联网界从此就多了一个新的名词-WebApp(意为基于WEB形式的应用程序,运行在高端的移动终端设备)。

开发者们都知道在高端智能手机系统中有两种应用程序:一种是基于本地(操作系统)运行的APP;一种是基于高端机的浏览器运行的WebApp,本文将主要讲解后者。

WebApp与Native App有何区别呢?

Native App:

1、开发成本非常大。
一般使用的开发语言为JAVA、C++、Objective-C。

2、更新体验较差、同时也比较麻烦
每一次发布新的版本,都需要做版本打包,且需要用户手动更新(有些应用程序即使不需要用户手动更新,但是也需要有一个恶心的提示)。

3、非常酷
因为native app可以调用IOS中的UI控件以UI方法,它可以实现WebApp无法实现的一些非常酷的交互效果

4、Native app是被Apple认可的
Native app可以被Apple认可为一款可信任的独立软件,可以放在Apple Stroe出售,但是Web app却不行。

Web App:
1、开发成本较低
使用web开发技术就可以轻松的完成web app的开发

2、升级较简单
升级不需要通知用户,在服务端更新文件即可,用户完全没有感觉

3、维护比较轻松
和一般的web一样,维护比较简单,它其实就是一个站点

Webapp说白了就是一个针对Iphone、Android优化后的web站点,它使用的技术无非就是HTML或HTML5、CSS3、JavaScript,服务端技术JAVA、PHP、ASP。

当然,因为这些高端智能手机(Iphone、Android)的内置浏览器都是基于webkit内核的,所以在开发WEBAPP时,多数都是使用HTML5和CSS3技术做UI布局。当使用HTML5和CSS3l做UI时,若还是遵循着一般web开发中使用HTML4和CSS2那样的开发方式的话,这也就失去了WEBAPP的本质意义了,且有些效果也无法实现的,所以在此又回到了我们的主题–webapp的布局方式和技术。

在此所说的移动平台前端开发是指针对高端智能手机(如Iphone、Android)做站点适配也就是WebApp,并非是针对普通手机开发Wap 2.0,所以在阅读本篇文章以前,你需要对webkit内核的浏览器有一定的了解,你需要对HTML5和CSS3有一定的了解。如果你已经对此有所了解,那现在就开始往下阅读吧……

1、首先我们来看看webkit内核中的一些私有的meta标签,这些meta标签在开发webapp时起到非常重要的作用
1 <meta content=”width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;” name=”viewport” />
2 <meta content=”yes” name=”apple-mobile-web-app-capable” />
3 <meta content=”black” name=”apple-mobile-web-app-status-bar-style” />
4 <meta content=”telephone=no” name=”format-detection” />

第一个meta标签表示:强制让文档的宽度与设备的宽度保持1:1,并且文档最大的宽度比例是1.0,且不允许用户点击屏幕放大浏览;
第二个meta标签是iphone设备中的safari私有meta标签,它表示:允许全屏模式浏览;
第三个meta标签也是iphone的私有标签,它指定的iphone中safari顶端的状态条的样式;
第四个meta标签表示:告诉设备忽略将页面中的数字识别为电话号码

2、HTML5标签的使用
在开始编写webapp时,哥建议前端工程师使用HTML5,而放弃HTML4,因为HTML5可以实现一些HTML4中无法实现的丰富的WEB应用程序的体验,可以减少开发者很多的工作量,当然了你决定使用HTML5前,一定要对此非常熟悉,要知道HTML5的新标签的作用。比如定义一块内容或文章区域可使用section标签,定义导航条或选项卡可以直接使用nav标签等等。

3、放弃CSS float属性
在项目开发过程中可以会遇到内容排列排列显示的布局(见下图),假如你遇见这样的视觉稿,哥建议你放弃float,可以直接使用display:block;

4、利用CSS3边框背景属性
这个按钮有圆角效果,有内发光效果还有高光效果,这样的按钮使用CSS3写是无法写出来的,当然圆角可以使用CSS3来写,但高光和内发光却无法使用CSS3编写,这个时候你不妨使用-webkit-border-image来定义这个按钮的样式。-webkit-border-image就个很复杂的样式属性。

5、块级化a标签
请保证将每条数据都放在一个a标签中,为何这样做?因为在触控手机上,为提升用户体验,尽可能的保证用户的可点击区域较大。

6、自适应布局模式
在编写CSS时,我不建议前端工程师把容器(不管是外层容器还是内层)的宽度定死。为达到适配各种手持设备,我建议前端工程师使用自适应布局模式(支付宝采用了自适应布局模式),因为这样做可以让你的页面在ipad、itouch、ipod、iphone、android、web safarik、chrome都能够正常的显示,你无需再次考虑设备的分辨率。

7、学会使用webkit-box
上一节,我们说过自适应布局模式,有些同学可能会问:如何在移动设备上做到完全自适应呢?很感谢webkit为display属性提供了一个webkit-box的值,它可以帮助前端工程师做到盒子模型灵活控制。

8、如何去除Android平台中对邮箱地址的识别
看过iOS webapp API的同学都知道iOS提供了一个meta标签:用于禁用iOS对页面中电话号码的自动识别。在iOS中是不自动识别邮件地址的,但在Android平台,它会自动检测邮件地址,当用户touch到这个邮件地址时,Android会弹出一个框提示用户发送邮件,如果你不想Android自动识别页面中的邮件地址,你不妨加上这样一句meta标签在head中1 <meta content=”email=no” name=”format-detection” />

9、如何去除iOS和Android中的输入URL的控件条
你的老板或者PD或者交互设计师可能会要求你:能否让我们的webapp更加像nativeapp,我不想让用户看见那个输入url的控件条?

答案是可以做到的。我们可以利用一句简单的javascript代码来实现这个效果
1 setTimeout(scrollTo,0,0,0);

请注意,这句代码必须放在window.onload里才能够正常的工作,而且你的当前文档的内容高度必须是高于窗口的高度时,这句代码才能有效的执行。

10、如何禁止用户旋转设备
我曾经也想禁止用户旋转设备,也想实现像某些客户端那样:只能在肖像模式或景观模式下才能正常运行。但现在我可以很负责任的告诉你:别想了!在移动版的webkit中做不到!

至少Apple webapp API已经说到了:我们为了让用户在safari中正常的浏览网页,我们必须保证用户的设备处于任何一个方位时,safari都能够正常的显示网页内容(也就是自适应),所以我们禁止开发者阻止浏览器的orientationchange事件,看来苹果公司的出发点是正确的,苹果确实不是一般的苹果。

iOS已经禁止开发者阻止orientationchange事件,那Android呢?对不起,我没有找到任何资料说Android禁止开发者阻止浏览器orientationchange事件,但是在Android平台,确实也是阻止不了的。

11、如何检测用户是通过主屏启动你的webapp
看过Apple webapp API的同学都知道iOS为safari提供了一个将当前页面添加主屏的功能,按下iphoneipodipod touch底部工具中的小加号,或者ipad顶部左侧的小加号,就可以将当前的页面添加到设备的主屏,在设备的主屏会自动增加一个当前页面的启动图标,点击该启动图标就可以快速、便捷的启动你的webapp。从主屏启动的webapp和浏览器访问你的webapp最大的区别是它清除了浏览器上方和下方的工具条,这样你的webapp就更加像是nativeapp了,还有一个区别是window对像中的navigator子对象的一个standalone属性。iOS中浏览器直接访问站点时,navigator.standalone为false,从主屏启动webapp时,navigator.standalone为true, 我们可以通过navigator.standalone这个属性获知用户当前是否是从主屏访问我们的webapp的。在Android中从来没有添加到主屏这回事!

12、如何关闭iOS中键盘自动大写
我们知道在iOS中,当虚拟键盘弹出时,默认情况下键盘是开启首字母大写的功能的,根据某些业务场景,可能我们需要关闭这个功能,移动版本webkit为input元素提供了autocapitalize属性,通过指定autocapitalize=”off”来关闭键盘默认首字母大写。

13、iOS中如何彻底禁止用户在新窗口打开页面
有时我们可能需要禁止用户在新窗口打开页面,我们可以使用a标签的target=”_self“来指定用户在新窗口打开,或者target属性保持空,但是你会发现iOS的用户在这个链接的上方长按3秒钟后,iOS会弹出一个列表按钮,用户通过这些按钮仍然可以在新窗口打开页面,这样的话,开发者指定的target属性就失效了,但是可以通过指定当前元素的-webkit-touch-callout样式属性为none来禁止iOS弹出这些按钮。这个技巧仅适用iOS对于Android平台则无效。

14、iOS中如何禁止用户保存图片\复制图片
我们在第13条技巧中提到元素的-webkit-touch-callout属性,同样为一个img标签指定-webkit-touch-callout为none也会禁止设备弹出列表按钮,这样用户就无法保存\复制你的图片了。

15、iOS中如何禁止用户选中文字
我们通过指定文字标签的-webkit-user-select属性为none便可以禁止iOS用户选中文字。

16、iOS中如何获取滚动条的值
桌面浏览器中想要获取滚动条的值是通过document.scrollTop和document.scrollLeft得到的,但在iOS中你会发现这两个属性是未定义的,为什么呢?因为在iOS中没有滚动条的概念,在Android中通过这两个属性可以正常获取到滚动条的值,那么在iOS中我们该如何获取滚动条的值呢?
通过window.scrollY和window.scrollX我们可以得到当前窗口的y轴和x轴滚动条的值。

17、如何解决盒子边框溢出
当你指定了一个块级元素时,并且为其定义了边框,设置了其宽度为100%。在移动设备开发过程中我们通常会对文本框定义为宽度100%,将其定义为块级元素以实现全屏自适应的样式,但此时你会发现,该元素的边框(左右)各1个像素会溢了文档,导致出现横向滚动条,为解决这一问题,我们可以为其添加一个特殊的样式-webkit-box-sizing:border-box;用来指定该盒子的大小包括边框的宽度。

18、如何解决Android 2.0以下平台中圆角的问题
如果大家够细心的话,在做wap站点开发时,大家应该会发现android 2.0以下的平台中问题特别的多,比如说边框圆角这个问题吧。
在对一个元素定义圆角时,为完全兼容android 2.0以下的平台,我们必须要按照以下技巧来定义边框圆角:
1\-webkit这个前缀必须要加上(在iOS中,你可以不加,但android中一定要加);
2\如果对针对边框做样式定义,比如border:1px solid #000;那么-webkit-border-radius这属性必须要出现在border属性后。
3\假如我们有这样的视觉元素,左上角和右上角是圆角时,我们必须要先定义全局的(4个角的圆角值)-webkit-border-radius:5px;然后再依次的覆盖左下角和右下角,-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-border:0;否则在android 2.0以下的平台中将全部显示直角,还有记住!-webkit这个前缀一定要加上!

19、如何解决android平台中页面无法自适应
虽然你的html和css都是完全自适应的,但有一天如果你发现你的页面在android中显示的并不是自适应的时候,首先请你确认你的head标签中是否包含以下meta标签:
1 <meta name=”viewport” content=”width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0;” />
如果有的话,那请你再仔细的看清楚有没有这个属性的值width=device-width,如果没有请立即加上吧!

20、如何解决iOS 4.3版本中safari对页面中5位数字的自动识别和自动添加样式
新的iOS系统也就是4.3版本,升级后对safari造成了一个bug:即使你添加了如下的meta标签,safari仍然会对页面中的5位连续的数字进行自动识别,并且将其重新渲染样式,也就是说你的css对该标签是无效的。
1 <meta name=”format-detection” content=”telphone=no” />

我们可以用一个比较龌龊的办法来解决。比如说支付宝wap站点中显示金额的标签,我们都做了如下改写:
1 <button class=”t-balance”style=”background:none;padding:0;border:0;”>95009.00</button>元 

HTML5 Geolocation API(转)

如果你是在特意寻找有关HTML5 Geolocation文章,那相信你应该对此有所了解,可能你不太清楚HTML5 Geoloation API的使用或者你想找一个有关HTML5 Geolocation的Demo。我相信你和我一样是一个爱学习的前端工程师,爱关注web前沿技术。下面就让我们一起来看看HTML5 Geoloatio的使用。

如果你对HTML5 Geolocation非常饥渴,你可以先看看HTML5全球地理位置定位系统演示再阅读文章。

对于HTML5 Geoloatio的介绍我在此不多说,你可以Google一下。假如你想了解地理定位想关的信息,你也可以利用Google获取这些知识,本文主要讲HTML5 Geoloatio API的使用。
我们首先来看一下HTML5 Geolocation在主流浏览器中的支持情况,目前HTML5 Geolocation在以下浏览器和操作系统中已被支持:
1\带有Gears的Chrome;
2\Firefox3.5+
3\Opera10.0+
4\Safari4.0+
5\iOS3.0+
6 \Android2.0+
有些不支持的HTML5 Geolocation的浏览器(如Internet Explorer),可以通过安装Gears插件的形式获取用户Geolocation。
我们再来看看HTML5 Geolocation隐私
HTML5 Geolocation规范提供了一套保护用户隐私的机制,阻碍浏览器得到用户的明确许可,否则浏览不可获取用户的当前地理位置数据。
用户访问使用HTML5 Geolocation的站点,会触发隐私保护机制,如下图在iPhone中的Safari触发HTML5 Geolocation隐私保护机制
iPhone中Safari触发HTML5 Geolocation隐私保护机制
考虑到用户的隐私,我们建议在使用HTML5 Geolocation时,一定要告知用户:
1\会收集用户的地理位置数据
2\为何收集用户的地理位置数据
3\位置数据保存的时间
4\用户如何更新他的位置数据
5\如何使用用户的地理位置数据
在开始使用HTML5 Geolocation API前,我们必须要检查浏览器是否支持HTML5 Geolocation

if (navigator.geolocation) {
  //do something
}else{
  alert('Sorry,your device not support geolocation!');
}

继续探讨HTML5 Geolocation API。浏览器支持HTML5 Geolocation,我们如何获取用户的当前地理位置信息?

navigator.geolocation.getCurrentPosition(successCallback,errorCallback,positionOptions);

navigator.geolocation对象有一个方法getCurrentPosition用来获取用户当前位置信息,该方法带有三个参数:
1\successCallback:成功获取用户位置信息后的回调函数
2\errorCallback:获取用户位置信息失败时的回调函数
3\positionOptions:可选。获取用户位置信息的配置参数
我们先来看看successCallback

var success = function(position){
            var lat = position.coords.latitude,
                  lon = position.coords.longitude,
                  info = document.getElementById('renderData');

            console.log(position);

            if (lat) {
                info.innerHTML = '';

                info.innerHTML += '<h3>From your geolocation:</h3>' +
                '<ul><li><strong>Latitude:</strong>' +
                lat +
                '</li><li><strong>Longitude:</strong>' +
                lon +
                '</li><li><strong>Region Name:</strong>' +
                geoip_region_name() +
                '</li><li><strong>City:</strong>' +
                geoip_city() +
                '</li>' +
                '<li><strong>Country:</strong>' +
                geoip_country_name() +
                '</li>' +
                '<li><strong>Country Code:</strong>' +
                geoip_country_code() +
                '</li>' +
                (window.JSON || JSON && JSON.stringify ? '<li>' + JSON.stringify(position) + '</li>' : '') +
                '</ul>';
            }
        };

successCallback非常简单,它带有一个参数,表示已经获取到的用户位置数据(positionData),对象字面量格式。该对象包含两个属性coords\timestamp,
coords属性中包含了以下7个值:
1\accuracy:准确度
2\latitude:纬度
3\longitude:经度
4\altitude:海拔高度
5\altitudeAcuracy:海拔高度的精确度
6\heading:行进方向
7\speed:地面的速度
以上七个属性,如果浏览器没有获取到它们的值,则返回null。\
timestamp属性在实际开发中用处不大。
我们再看errorCallback

var error = function(error){
                        var info = document.getElementById('renderData');

                        info.innerHTML = '';

                        info.innerHTML = info.innerHTML += '<h3>Error log:</h3>' +
                        '<ul><li><strong>Error Code:</strong>' +
                        error.code +
                        '</li><li><strong>Error Message:</strong>' +
                        error.message +
                        '</li></ul>';
                    }

errorCallback和successCallback一样的简单。errorCallback也带有一个参数,表示HTML5 Geolocation返回的错误数据,对象字面量格式,它包含以下两个属性message\code
1\message:错误信息
2\code:错误代码。
错误代码:
0(UNKNOW_ERROR)表示不包括在其它错误代码中的错误,这里可以需要在message中查找错误信息;
1(PERMISSION_DENIED)表示用户拒绝浏览器获取位置信息的请求
2(POSITION_UNAVALIABLE)表示获取位置信息失败
3(TIMEOUT)表示获取位置信息超是。必须在options中指定了timeout值时才有可能发生这种错误
某些浏览器可能没有message属性的值,则返回null。
最后我们看看可选参数positionOptions,positionOptions的数据格式为JSON。
positionOptions有三个可选的属性enableHighAcuracy\timeout\maximumAge
1\enableHighAcuracy:布尔值。表示是否启用高精确度模式,如果启用这种模式,浏览器在获取位置信息时可能需要耗费更多的时间。
2\timeout:整数。表示浏览需要在指定的时间内获取位置信息,否则触发errorCallback。
3\maximumAge:整数/常量(infinity)。表示浏览器重新获取位置信息的时间间隔。
你是否很疑惑timeout和maximumAge?
timeout很好理解。那maximumAge如何使用呢?
如果浏览器没有在maximumAge设定的时间内更新过位置数据,它就必须重新发起请求。如果将maximumAge设置为0,则浏览器每次请求时都需要重新获取位置数据,如果设置为常量infinity则意味着浏览器永远不再获取位置数据。

在某些应用开发中,我们可以需要实时获取\检测用户的位置信息,还有HTML5 Geolocation的程序设计师考虑到这一点,为我们设计了watchPosition方法,watchPosition就像一个追踪器一样实时监视用户的位置变化,只要用户的位置发生变化,只要开发者为HTML5 Geolocation指定了watchPostion,浏览器就发触发successCallback或errorCallback。

navigator.geolocation.watchPosition(successCallback,errorCallback,positionOptions);

如果你的应用程序中为HTML5 Geolocation添加了watchPosition,那么你还应该为用户提供关闭这种实时监视位置信息变化的功能,这里我们可以使用HTML5 Geolocation的clearWatch方法。
HTML5 Geolocation的clearWatch方法接受一个watchPosition ID为参数。意思就是清除指定的watchPosition。watchPosition ID来自于watchPosition的返回值,每个watchPosition都会返回一个watchPosition ID。

var watchPositionID = navigator.geolocation.watchPosition(successCallback,errorCallback,positionOptions);
navigator.geolocation.clearWatch(watchPositionID);

以上就是目前HTML5 Geolocation API中的所有接口的用法。
HTML5 Geolocation可以帮助开发者获取用户的纬度和经度的数据,但无法获取到更加详细的用户位置数据。比如国家代码\城市等等。
其实在实际项目开发中我们可能需要借助第三方工具(比如Google Map)来完成产品的需求。比如说帮助用户自动选择省份\地区,帮助用户做地图坐标定位等等。
HTML5全球地理位置定位系统演示中使用了GeoIP来获取用户的国家代码\国家名称\省份名称\城市名称。

firefox7 支持text-overflow: ellipsis

firefox7 发布后正式支持 text-overflow: ellipsis (…)以后再写省略号效果就省事多了,具体代码如下:


<div style="width:200px;height:25px;line-height:25px;overflow:hidden;border:1px solid #333;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-family:'宋体';">irefox 7正式支持 text-overflow: ellipsis终于赶上IE6的脚步</div>

CSS3 Gradient Backgrounds(css3渐变实例)

css3各种渐变实例

http://css-tricks.com/examples/CSS3Gradient/

HTML5开发者需要了解的技巧和工具汇总(转)

HTML5现在已经成为了Web开发中的热门话题,大多数现代浏览器(Safari、Chrome,Firefox,IE10和移动设备)都支持 HTML5。即使HTML5的规范还没有制定完成,但许多开发者已经将其作为Web开发项目中的主要技术。一些网站巨头,如Google、 Facebook、Twitter和YouTube等,都建立在HTML5基础上。

HTML5中最令人兴奋的功能莫过于画布(canvas)和强大的表单功能,画布功能已经可以在大部分浏览器中完美体验(除了IE),但对于新表单元素的支持还不是太好。对Web开发者来说,是时候开始HTML5开发了。

要进行HTML5开发,本文中的一些技巧、工具可以让你缩短学习的时间,提高开发的效率。

一、HTML5支持测试列表

在开始之前,你需要了解现代的浏览器以及移动平台对于HTML5的支持情况。

二、让HTML5元素可用

老版本的IE浏览器不能识别新的HTML元素。但是,可以使用一些JavaScript或CSS解决方案来弥补这个缺陷。

  • HTML5Shiv:此脚本可以使IE浏览器识别HTML5元素。
  • HTML5 Enabler:功能与HTML5Shiv类似。
  • Modernizr:它使得开发者可以在支持HTML5和CSS3的浏览器中充分利用HTML5和CSS3的特性进行开发,同时又不会牺牲其他不支持这些新技术的浏览器的控制。
  • HTML5 Reset:它提供了一组HTML、CSS文件,让你能够以最少的时间来启动一个新的项目。它使用modernizr来支持HTML5和CSS3。

三、浏览器插件

下面是一些JavaScript插件,可以弥补一些浏览器对HTML5的支持问题。

1. VideoJS

VideoJS是一个HTML5的视频播放器,可以在所有浏览器中使用,包括IE6和移动设备。对于不支持HTML5的浏览器则自动使用Flash播放器来播放。

2. AudioJS

HTML音频播放器。用来让HTML5 的 <audio> 标签可以在各种浏览器上使用,包括移动设备。

3. HTML5Widget

HTML5的表单模块,包括日历,调色板,滑动部件,客户端验证等。

4. Webforms2

HTML5 表单属性的支持,例如pattern、required和autofocus。

5. LimeJS

LimeJS是HTML5的游戏框架,用于为现代触摸设备和桌面浏览器创建快速、本地化的游戏。

6. FlexieJS

支持CSS3弹性盒子模型(Flexible Box Model)。

四、在线工具

此外,还有一些在线工具,可以帮助开发者加快HTML5项目的开发。

1. HTML5 Boilerplate

HTML5Boilerplate是一个HTML / CSS /JS模板,是实现跨浏览器正常化、性能优化、稳定的可选功能如跨域Ajax和Flash的最佳实践。开发者称之为技巧集合,目的是满足你开发一个跨浏览器,并且面向未来的网站的需求。

2. Switch to HTML5

非常有用的在线工具,可以根据你的喜好生成HTML5文档结构。

3. Initializr

Initializr是一个HTML5模板生成器,以帮助你开始HTML5项目的开发 。它建立在HTML5 Boilerplate之上

4. HTML5 Visual 速查表

5. HTML5 Canvas 速查表

6. HTML5 笔记

五、其他

你可以通过下面的链接来跟踪HTML5的更新。

HTML5追踪

你可以通过下面的链接获得HTML5网站的设计灵感。这个网站库中包含了大量的使用HTML5技术的网站。

HTML5Gallery

文章出自:queness.com

译文出自:ITeye

(转)javascript编程容易出现的11个错误

javascript-11-mistake
javascript是比较容易学的。但是,对于这门语言需要有一些值得注意的地方。本文将指出javascript编程中可能犯过的10个错误

错误1-使用全局变量

如果你刚开始javascript编程,可能会觉得全局变量很好用。事实上,刚开始javascript编程,你可能不知道使用全局变量会带来什么 麻烦。在同一个页面中,全局变量可以在任何内嵌的javascript代码段中或是该页面加载的不同的js文件中,都能访问到。这听起来很强大,是吗?这 就使得全局变量可以随时随地的被修改赋值。
事实上这样很糟!
这样做会导致变量在意料之外被修改重写。假设有一个网店,需要用javascript计算并显示购物车所有商品的价格总和(当然,服务器端还会进行重新计算,这里只是为了增强用户的体验)。可能会编写代码如下:

  1. var total = 0, // total price
  2. tax = 0.05; // 5%

现在,还需要用javascript代码在网站上展示一些信息,或则是做一个商品仓库。代码如下:

  1. var total = 15; // number of tweets pulled from twitter

或则是如下代码:

  1. var tax = function () { /* … */ }; // Trigger Animation eXperience function

现在,出现问题了:两个重要的变量被重写,但可能还没被意识到。这样代码运行会出错,会花费很多时间来跟踪和修复该错误。
那该如何解决呢?简言之—“封装”:当然封装有很多方法可以实现。第一种做法是将代码放入一个匿名的自调函数中。代码如下:

  1. (function () {
  2. var total = 0, tax = 0.05;
  3. // other code
  4. }());

这样做,在函数外部是绝对不能访问到函数内部定义的变量。这就形成了个人的代码空间,但是这样就不能公开部分方法或属性。例如,想要创建一个购物车,定义一个总价的变量,作为公共属性,这种情形下可以采用模块式编程。

  1. var cartTotaler = (function () {
  2. var total = 0; tax = 0.05;
  3. // other code
  4. return {
  5. addItem : function (item) { },
  6. removeItem : function (item) { },
  7. calculateTitle : function () { }
  8. };
  9. }());

关于全局变量有一点值得注意,如果不用关键词var来声明创建变量,那么javascript引擎会默认将该变量定义为全局变量。

  1. (function () {
  2. tax = 0.05;
  3. }());
  4. var totalPrice = 100 + (100 * tax); // 105

这里的变量tax在函数外部也是可以被访问的,因为在定义tax的时候没有使用var关键词。

错误2-不加分号

每句javascript语句必须以分号结尾。在编程时如果忘了加分号,这时javascript编解析器会自动加上。那我们在编程的时候是不是就可以完全不用浪费时间去加分号呢?
但是在一些语句中,分号是必不可少的。如for循环语句中的分号是必不可少的,否则会报语法错误。那么语句末尾的分号呢?
Javascript社区已经讨论过该问题。下面是本文的看法:你的代码,只要是被javascript解析器修改过(即便是很小的修改,如添加分号),就可能会出现一些你意料之外的结果。看看下面这段javascript代码:

  1. function returnPerson (name) {
  2. return
  3. {
  4. name : name
  5. };
  6. }

该方法看起来会返回一个对象,但事实上,javascript解析器会在return后面紧接着添加一个分号,这就导致该函数返回undefined。Return后的对象会被忽略。解决方法很简单,代码如下:

  1. return {
  2. name : name
  3. };

在javascript编程中应严格要求自己添加分号,这个习惯并不难。当然,作为一名web开发人员,你可能也会用到其他的语言(如php),这些语言都是严格要求以分号结尾的。你可以把这些编程语言的习惯带到javascript编程中来。
作者注解:除了你完全肯定可以被忽略的地方,你都不可以忽略添加分号。

错误3-使用==

如果你问一个javascript编程者,在javascript编程中通常会犯什么错误。他/她很可能会说,使用= = =来代替= =。这是什么意思呢?
试试下面的代码:

  1. if (1 == 1) {
  2. console.log(“it’s true!”);
  3. }

代码如你所愿的输出了“it’s true!”那再试试下面的代码:

  1. if (1 == ’1′) {
  2. console.log(“it’s true!”);
  3. }

这段代码在控制台中尽然也输出了“it’s true!”,但其实这并不是你所期望的输出。这里的==运算符转换了运算数的类型,从而使得两个运算数相等了。这里if语句中的==运算符使得右边string类型的“1”变成了number型的1。
想要得到你想要的输出,这里应该用= = =运算符来代替= =。===不会强制转换运算数的类型,这样才能如你所期望的。同样地,用!= =运算符来替换!=。下面是用==来做比较,得出的结果令人意外。

  1. ” == ’0′ // false
  2. ’0′ == ” // true
  3. false == ’0′ // true
  4. ‘ \t\r\n ‘ == 0 // true

错误4-使用数据类型的包装对象

Javascript提供了各个数据类型的包装对象。

  1. new Number(10);
  2. new String(“hello”);
  3. new Boolean(true);
  4. new Object();
  5. new Array(“one”, “two”, “three”);

首先,它们并不好用。上面的代码可以用更少的代码来实现,如下:

  1. 10;
  2. “hello”;
  3. true;
  4. {};
  5. ["one", "two", "three"];

但是这两种方式还是有所不同的。下面是douglas crockford的观点:
例如用new Boolean(false)创建一个对象,该对象有一个方法valueOf,调用该方法会返回构造器的值。
这意味着,如果运行typeof new Number(10)或者是typeof new String(‘hello’),将返回‘object’,而不是’number’或’string’.另外,用数据类型的包装还会引发一些意料之外的结果。
那么为什么javascript要提供数据类型的包装对象呢?这是因为javascript解析器内部会调用。简单的数据类型是没有方法的(因为它们不是 对象),所以当调用简单类型的数据的方法时(如’hello’.replace(‘ello’, ‘i’)),javascript会调用String包装对象来创建一个临时的string对象,然后调用该对象的方法,完成调用后会删除这个临时对象。
所以不要用数据类型的包装对象来创建简单类型的数据。
注意:本来不用这么说明的,但本文还是想明确的告诉初学者:不是说不使用它们和new(尽管有些是推荐使用的),这里需要特别指出的是,这个建议特别针对这些数据类型,如:number、string、Boolean、array和空对象。

错误5-在使用for-in时不对属性检查

我们都很熟悉遍历数组,但是你可能还希望能遍历对象的属性。(题外话:array事实上是属性名为数字的对象)。这是可以用for-in循环语句,代码如下:

  1. var prop, obj = { name: “Joe”, job: “Coder”, age: 25 };
  2. for (var prop in obj) {
  3. console.log(prop + “: ” + obj[prop]);
  4. }

运行上面的代码,输出如下:

  1. name: Joe
  2. job: Coder
  3. age: 25

但是,浏览器中for-in遍历对象属性和方法时会包括对象原型链上的所有属性和方法。但绝大多数属性是不希望被枚举出来的。可以用hasOwnProperties方法来检测属性是否属于对象。代码如下:

  1. Function Dog (name) {
  2. this.name = name;
  3. }
  4. Dog.prototype.legs = 4;
  5. Dog.prototype.speak = function () {
  6. return “woof!”;
  7. };
  8. var d = new Dog(“Bowser”);
  9. for (var prop in d) {
  10. console.log( prop + “: ” + d[prop] );
  11. }
  12. console.log(“=====”);
  13. for (var prop in d) {
  14. if (d.hasOwnProperty(prop)) {
  15. console.log( prop + “: ” + d[prop] );
  16. }
  17. }
  18. // Output
  19. // name: Bowser
  20. // legs: 4
  21. // speak: function () {
  22. return “woof!”;
  23. // }
  24. // =====
  25. // name: Bowser

有时,只希望枚举列出对象的的属性,不包括方法。可以用typeof方法,代码如下:

  1. for (var prop in d) {
  2. if (typeof d[prop] !== ‘function’) {
  3. console.log( prop + “: ” + d[prop] );
  4. }
  5. }

不管怎么样,在用for-in循环时要确保对属性进行检测,以避免得到你意料之外的结果。

错误6-使用with或eval

幸运的是,现在大部分javascript教程都不会教你使用with或eval。但是一些老教程或名气不大的资料时(因为有时候好的资料在网上很难找到),可能会发现有使用with或eval。
下面是两个不用with的主要原因:
1、 它会降低代码性能
2、 不易于代码阅读

第一点是它与生俱来的。第二点,看看下面的代码,这里用with访问person对象的name、age属性。

  1. var person = { name: “Joe”, age : 10 };
  2. with (person) {
  3. console.log(name); // Joe
  4. console.log(age); // 10
  5. }

但是,若果有一个变量和对象其中一个属性同名,那用with会发生什么呢?事实上,这种情况下,访问变量会引用那个变量而不是对象的属性。另一个值 得注意的是,在with语句中,如果访问的属性不存在或对象不存在,就不能给对象添加属性,同时会使得作用域链上with作用域后的那个作用域中创建一个 变量。

  1. var person = { name: “Joe”, age : 10 },
  2. name = “Billy”;
  3. with (person) {
  4. console.log(name); // Billy
  5. job = “Designer”;
  6. }
  7. console.log(person.job); // undefined;
  8. console.log(job); // Designer

那eval呢?它可以接受一个字符串参数,并且解析执行改字符串。

这听起来没有什么不好,甚至觉得很棒,对吗?但问题就是这太棒了!与其将一连串字符串将给它来解析执行,为什么不直接编写在程序中呢?不该这么做的原因如下:

  1. 完全可以直接编写在代码中。
  2. eval解析很慢的,性能跟with差不多。

eval的用法是在非运行时运行环境。可以从服务器端或客户端获取代码。难道真的想你的网站用户来底控制你的代码?这样不就意味着你的网站向无数的黑客敞开了大门。用eval就好比,离开了家,并告诉大家钥匙就是门口垫子下面。如果你爱自己或你的用户,就不要用eval。

错误7-在用parseInt时不用基数

Javascript提供了一个非常有用的方法parseInt,它可以将字符串转换为数值。

  1. parseInt(“200″); // 200
  2. parseInt(“043″); // 35

结果是不是令人觉得意外?第二句为什么不是43?事实上,parseInt方法不仅仅是只能把字符串当做十进制数来转换。当parseInt的第一 个参数是以0开头,它就会把字符串当作是八进制数来转换。这就是不使用基数出现的意料之外结果。第二个参数–基数,会指定parseInt方法把字符串当 做什么进制的数来转换。(当然,它的返回值永远是十进制数)

  1. parseInt(“020″, 10); // 20
  2. parseInt(“100″, 2); // 4

错误8 if和while语句不使用{}

Javascript最明显的特点是语法要求不那么严格。但正是这样的特点,有时会带来麻烦。If和while语句的{}就会引起一些麻烦。{}是根据if条件成立时执行代码语句的条数来用的。

  1. if (true)
  2. console.log(“inside the if statement”);

这里看起来没什么问题,因为这里的执行语句只有一句

  1. var arr = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"],
  2. i = arr.length – i;
  3. while (i) console.log( arr[i--] );

但是这样做不易于阅读:首先,不用{}代码结构看起来不是那么清晰。

  1. if (true)
  2. console.log(“inside the if-statement.”);
  3. console.log(“outside the if-statement.”);

看看上面的代码,第二行console语句是不属于if执行语句的,但是这里它看起来像是if的执行语句。使用{}会使结构更清晰。同时,如果你想在if的执行代码中添加一句,也需要使用{}。习惯使用{}并不是一件难事。

错误9-单个单个地插入dom元素

这并不是javascript自身的问题。99%100的javascript编程都会涉及DOM操作,在对DOM操作上会犯很多错误,但这是最明显的一个。
DOM操作会使浏览器重绘页面,所以如果有一连串的元素一个接一个的插入页面中,这会急剧增加浏览器渲染页面的负担。

  1. var list = document.getElementById(“list”),
  2. items = ["one", "two", "three", "four"],
  3. el;
  4. for (var i = 0; items[i]; i++) {
  5. el = document.createElement(“li”);
  6. el.appendChild( document.createTextNode(items[i]) );
  7. list.appendChild(el); // slow, bad idea
  8. }

Document fragments 是一个DOM元素容器,可以使用它同时添加这些元素到页面中。Document fragment自身不是一个DOM节点,它不会在页面DOM树中显示,并且在把它插入DOM之前它是不可见的。下面是它的用法:

  1. var list = document.getElementById(“list”),
  2. frag = document.createDocumentFragment(),
  3. items = ["one", "two", "three", "four"],
  4. el;
  5. for (var i = 0; items[i]; i++) {
  6. el = document.createElement(“li”);
  7. el.appendChild( document.createTextNode(items[i]) );
  8. frag.appendChild(el); // better!
  9. }
  10. list.appendChild(frag);

非常快速、简洁!

错误10-不懂javascript

许多人不花时间来认真地学习javascript。
Javascript并不等于jquery。这是否吓到你了?如果你会犯以上列出的错误,那么你需要认真地学习javascript。 Javascript是一门语言,一门基本上不用学习就可以使用的语言,这就导致许多人不花时间来认真学习。千万不要这么做,已经有太多太多的教程指出这 样做的弊端,你没有借口不认真学习javascript。如果你只是了解jquery(或mootools,或别的),那么你学习了解 javascript的出发点就已经错了。

错误11-严格遵循以上的规则

“Rules are made to be broken.”(规则是用来被打破的。)

虽然本文列举了以上规则,但像任何事一样,规则是用来被打破的。如果是刚开始学习javascript,你会严于律己,严格遵循以上规则。但是到了 真正理解了为什么要遵循以上规则的原因后,你才会知道灵活运用以上规则。例如,eval被反复的说到不能用,但是它却是唯一能解析服务器端返回json字 符串的方法。当然这里在运用它时会做很多安全的检测(你可能会用到一个javascript库)。这里想要指明的是,在需要的地方,不应该害怕犯错,大胆 的运用它。当然,永远不要犯错误10所指出的问题。

结论:

如果你是javascript新手,希望以上的内容对你javascript编程有所帮助。如果你是一个资深javascript工程师,如过这里有遗漏的,请在留言板中留言告知大家。

本文翻译自《The 11 JavaScript Mistakes you’re Making》

原文地址:http://www.36ria.com/4479

转:javascript contains方法

IE有许多好用的方法,后来都被其他浏览器抄袭了,比如这个contains方法。如果A元素包含B元素,则返回true,否则false。唯一不支持这个方法的是IE的死对头firefox。

提示:你可以先修改部分代码再运行。

不过火狐支持compareDocumentPosition() 方法,这是W3C制定的方法,标准浏览器都支持,不过实用性性很差,因此没有什么人用,推广不开来。它的使用形式与contains差不多,但返回的不是一个布尔值,而是一个很奇怪的数值,它是通过如下方式累加计算出来的:

Bits Number Meaning
000000 0 元素一致
000001 1 节点在不同的文档(或者一个在文档之外)
000010 2 节点 B 在节点 A 之前
000100 4 节点 A 在节点 B 之前
001000 8 节点 B 包含节点 A
010000 16 节点 A 包含节点 B
100000 32 浏览器的私有使用

提示:你可以先修改部分代码再运行。

PPK给出如下解决方法。

if (window.Node &amp;&amp; Node.prototype &amp;&amp; !Node.prototype.contains){  

   Node.prototype.contains = function (arg) {  

     return !!(this.compareDocumentPosition(arg) &amp; 16)  

   }  

 } 

我搞出个更短的:

if(!!window.find){  

  HTMLElement.prototype.contains = function(B){  

    return this.compareDocumentPosition(B) - 19 &gt; 0  

  }  

} 

提示:你可以先修改部分代码再运行。

descendantOf: function(element, ancestor) {
    if (element.compareDocumentPosition)
    return (element.compareDocumentPosition(ancestor) &amp; 8) === 8;  

  if (ancestor.contains)
    return ancestor.contains(element) &amp;&amp; ancestor !== element;  

  while (element = element.parentNode)
    if (element == ancestor) return true;  

  return false;  

},

原文地址:http://www.cnblogs.com/rubylouvre/archive/2011/05/30/1583523.html

转:js判断一个元素是否为另一个元素的子元素

用js判断一个元素是否为另一个元素的子元素,再做一些效果的时候经常用到,特别是和鼠标事件相关的应用中,比如一个浮层,在鼠标操作浮层内元素的时候浮层显示,当点击浮层外的元素的时候隐藏浮层。当然方法有很多,不过个人认为通过判断一个元素是否为另一个元素的子元素是最简单的实现方式之一。

function isParent (obj,parentObj){
    while (obj != undefined && obj != null && obj.tagName.toUpperCase() != 'BODY'){
        if (obj == parentObj){
            return true;
        }
        obj = obj.parentNode;
    }
    return false;
}

查看demo:http://www.css88.com/demo/isParent/
还有另外一种方法(contains)http://www.uedspace.com/blog/411.html

本文转自:http://www.css88.com/archives/3700

Chrome 中文版字体小于12px的解决方法

在中文版的chrome里,定义了小于12px的字体依然显示为12px.
解决办法:webkit的私有属性 html{-webkit-text-size-adjust:none;}
在此记录一下。

Yslow优化建议

转发小崔的一篇文章,很实用的优化建议:

之前介绍过一次 Yslow ,最近又遇到了网站优化方面的问题,复习一遍:


  1. 减少HTTP请求次数
    合并图片、CSS、JS,改进首次访问用户等待时间。
  2. 使用CDN
    就近缓存==>智能路由==>负载均衡==>WSA全站动态加速
  3. 避免空的src和href
    当link标签的href属性为空、script标签的src属性为空的时候,浏览器渲染的时候会把当前页面的URL作为它们的属性值,从而把页面的内容加载进来作为它们的值。测试
  4. 为文件头指定Expires
    使内容具有缓存性。避免了接下来的页面访问中不必要的HTTP请求。
  5. 使用gzip压缩内容
    压缩任何一个文本类型的响应,包括XML和JSON,都是值得的。旧文章
  6. 把CSS放到顶部
  7. 把JS放到底部
    防止js加载对之后资源造成阻塞。
  8. 避免使用CSS表达式
  9. 将CSS和JS放到外部文件中
    目的是缓存,但有时候为了减少请求,也会直接写到页面里,需根据PV和IP的比例权衡。
  10. 权衡DNS查找次数
    减少主机名可以节省响应时间。但同时,需要注意,减少主机会减少页面中并行下载的数量。
    IE浏览器在同一时刻只能从同一域名下载两个文件。当在一个页面显示多张图片时,IE 用户的图片下载速度就会受到影响。所以新浪会搞N个二级域名来放图片。
  11. 精简CSS和JS
  12. 避免跳转
    同域:注意避免反斜杠 “/” 的跳转;
    跨域:使用Alias或者mod_rewirte建立CNAME(保存域名与域名之间关系的DNS记录)
  13. 删除重复的JS和CSS
    重复调用脚本,除了增加额外的HTTP请求外,多次运算也会浪费时间。在IE和Firefox中不管脚本是否可缓存,它们都存在重复运算JavaScript的问题。
  14. 配置ETags
    它用来判断浏览器缓存里的元素是否和原来服务器上的一致。比last-modified date更具有弹性,例如某个文件在1秒内修改了10次,Etag可以综合Inode(文件的索引节点(inode)数),MTime(修改时间)和 Size来精准的进行判断,避开UNIX记录MTime只能精确到秒的问题。 服务器集群使用,可取后两个参数。使用ETags减少Web应用带宽和负载
  15. 可缓存的AJAX
    “异步”并不意味着“即时”:Ajax并不能保证用户不会在等待异步的JavaScript和XML响应上花费时间。
  16. 使用GET来完成AJAX请求
    当使用XMLHttpRequest时,浏览器中的POST方法是一个“两步走”的过程:首先发送文件头,然后才发送数据。因此使用GET获取数据时更加有意义。
  17. 减少DOM元素数量
    是否存在一个是更贴切的标签可以使用?人生不仅仅是DIV+CSS
  18. 避免404
    有些站点把404错误响应页面改为“你是不是要找***”,这虽然改进了用户体验但是同样也会浪费服务器资源(如数据库等)。最糟糕的情况是指向外部 JavaScript的链接出现问题并返回404代码。首先,这种加载会破坏并行加载;其次浏览器会把试图在返回的404响应内容中找到可能有用的部分当 作JavaScript代码来执行。
  19. 减少Cookie的大小
  20. 使用无cookie的域
    比如图片 CSS 等,Yahoo! 的静态文件都在 yimg.com 上,客户端请求静态文件的时候,减少了 Cookie 的反复传输对主域名 (yahoo.com) 的影响。
  21. 不要使用滤镜
    png24的在IE6半透明那种东西,别乱使,淡定的切成PNG8+jpg
  22. 不要在HTML中缩放图片
  23. 缩小favicon.ico并缓存

原文地址:http://uicss.cn/yslow/