- UID
- 864
- 斋米
-
- 斋豆
-
- 回帖
- 0
- 积分
- 62579
- 在线时间
- 小时
- 注册时间
- 2010-3-29
- 最后登录
- 1970-1-1
|
你知道世界上有多少种浏览器吗?除了我们熟知的IE, Firefox, Opera, Safari四大浏览器之外,世界上还有近百种浏览器。 几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的Chrome浏览器。由于Chrome出生名门,尽管他还是个小家伙,没有人敢小看他。以后,咱们常说浏览器的“四大才子”就得改称为“五朵金花”了。
$ @% `9 @; p% `; h 在网站前端开发中,浏览器兼容性问题本已让我们手忙脚乱,Chrome的出世不知道又要给我们添多少乱子。浏览器兼容性是前端开发框架要解决的第一个问题,要解决兼容性问题就得首先准确判断出浏览器的类型及其版本。
2 j# L2 l8 ^# o JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本。JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。! v- e7 m$ H/ X \3 @
我们先来分析一下各种浏览器的特征及其userAgent。/ w) B! V& w- r/ A* }+ v) i. J. s9 j
IE* N2 X0 ~- F' i4 Z" ]8 q* |
只有IE支持创建ActiveX控件,因此她有一个其他浏览器没有的东西,就是ActiveXObject函数。只要判断window对象存在ActiveXObject函数,就可以明确判断出当前浏览器是IE。而IE各个版本典型的userAgent如下:
1 h) R4 R1 Z8 @+ y+ f) v6 H! ~1 P) Y- E7 t
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)2 i+ l6 k- c9 c1 j; H4 [
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)/ `9 ~ a' [6 |! Z" D
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) {/ ~* ~& A% `* o; \# ]
Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)
4 B! Q. u8 r- u% K a* g6 Y$ o6 b5 s/ v# x
其中,版本号是MSIE之后的数字。8 q% v8 R2 \+ k
Firefox/ }$ e" [8 A4 m6 |9 i9 F ^
Firefox中的DOM元素都有一个getBoxObjectFor函数,用来获取该DOM元素的位置和大小(IE对应的中是getBoundingClientRect函数)。这是Firefox独有的,判断它即可知道是当前浏览器是Firefox。Firefox几个版本的userAgent大致如下:
! Z1 ~2 ~, R! D" }9 X: U Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.15 m2 d9 S9 E7 N. m( g2 d: D. s6 B
Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3
& D# [' `" Q1 z8 E Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12# i6 V. y2 E! P( s( P& u
其中,版本号是Firefox之后的数字。$ I) _4 Q, f# g/ o( w
" R8 b. e5 D8 \& C+ p7 G
Opera7 `7 g- }$ S, [% Z4 @: o' S8 e
Opera提供了专门的浏览器标志,就是window.opera属性。Opera典型的userAgent如下:
6 `, V- Q/ y: V: g6 ]/ e
1 T. V) A+ Z$ E& r% z. a6 e5 B Q# z. @ Opera/9.27 (Windows NT 5.2; U; zh-cn)
+ }# {6 C/ R! x. X4 F( \ Opera/8.0 (Macintosh; PPC Mac OS X; U; en)
% R6 Y7 O5 W" P( @7 t' e; s' P+ T Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0) g/ ~9 U1 X9 x' q0 f3 c8 @& Q0 z
0 X( `; y7 W1 k& r7 }! u 其中,版本号是靠近Opera的数字。+ X; v m% B- @4 ]3 w* M. ]
$ i, \ ^9 x+ n" ~- t
Safari
. m2 \5 ~6 Z, i& Y$ O, t: _) ]) A+ ~$ ^; `# X3 C2 H/ \* [
Safari浏览器中有一个其他浏览器没有的openDatabase函数,可做为判断Safari的标志。Safari典型的userAgent如下:: O3 }7 S7 L6 K8 H R7 F
2 @7 i: t) N0 G" S" \ Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.139 y4 p. n. ^5 ]1 x
Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3
: G! _. f M- }) Y; c E
1 g- ~$ {1 H6 J+ C$ {& Q$ Z 其版本号是Version之后的数字。: o0 Z3 [; n$ N5 E( ?
Chrome; p+ y" }. l9 x$ K! m3 Z1 P1 T
Chrome有一个MessageEvent函数,但Firefox也有。不过,好在Chrome并没有Firefox的getBoxObjectFor函数,根据这个条件还是可以准确判断出Chrome浏览器的。目前,Chrome的userAgent是:
! `) U- U; t1 X* c, J# ]
$ i: y" b) m5 H Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.135 f+ G' U7 q, ~
9 g! ^( U% {* p' I 其中,版本号在Chrome只后的数字。- x' t) L2 E. o9 X8 S' m5 m
有趣的是,Chrome的userAgent还包含了Safari的特征,也许这就是Chrome可以运行所有Apple浏览器应用的基础吧。
9 x1 M/ [: ^ O* U 只要了解了以上信息,我们就可以根基这些特征来判断浏览器类型及其版本了。我们会将判断的结果保存在Sys名字空间中,成为前端框架的基本标志信息,供今后的程序来读取。如果判断出谋种浏览器,Sys名字空间将有一个该浏览器名称的属性,其值为该浏览器的版本号。例如,如果判断出IE 7.0,则Sys.ie的值为7.0;如果判断出Firefox 3.0,则Sys.firefox的值为3.0。下面是判断浏览器的代码:
; @# k8 ~5 ]8 l; \$ }- E1 W, {/ U/ g& D8 s
! w L7 n. f+ g+ k' \ <script type="text/javascript">
" i0 F: C# m- ] | ?0 L var Sys = {};
9 r9 l' F9 I% U3 j/ A/ D4 a4 t5 T8 N" T var ua = navigator.userAgent.toLowerCase();
! Z# I, z# k. @( T- ~1 I if (window.ActiveXObject)2 ]: p, q' e8 h# _ g$ ?1 C6 V
Sys.ie = ua.match(/msie ([\d.]+)/)[1]9 T2 F$ ]' g+ N0 d3 J8 X
else if (document.getBoxObjectFor)
8 ]6 Z ^/ R2 d( H b& ?* [ Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1]$ P; O3 x/ j, f) U! R G$ y
else if (window.MessageEvent && !document.getBoxObjectFor)
. j. I7 r4 w0 g4 m$ B6 i% c4 e8 H Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1]
/ V' c7 Z- T6 d' I else if (window.opera)8 W8 [& t0 M& f% ~' g3 w
Sys.opera = ua.match(/opera.([\d.]+)/)[1]
7 V' K# j, n8 w* `5 u$ g else if (window.openDatabase)" U: \9 v! X- ? y# F2 _6 l
Sys.safari = ua.match(/version\/([\d.]+)/)[1];
4 Q. ]* l. d# D1 L+ W
7 @* a- c0 z% I9 @- X //以下进行测试+ e" z; x0 F+ @
if(Sys.ie) document.write('IE: '+Sys.ie);
+ N9 U4 i z9 p+ g) o if(Sys.firefox) document.write('Firefox: '+Sys.firefox);# @ ]# B; l8 E, V; w
if(Sys.chrome) document.write('Chrome: '+Sys.chrome);& J+ O. s2 R$ Y' w7 u% [6 P" `+ |
if(Sys.opera) document.write('Opera: '+Sys.opera);4 K: A' C7 |1 Y. O/ x. z z+ o
if(Sys.safari) document.write('Safari: '+Sys.safari);
. _4 r8 }- e, o </script>2 F8 t; r$ F0 k" V& _: w; C/ Q
7 d: t/ A. ~# v" |: Y* e- @
9 z. _' P" h& C1 D1 {/ _ 我们把对IE的判断放在第一,因为IE的用户最多,其次是判断Firefox。按使用者多少的顺序来判断浏览器类型,可以提高判断效率,少做无用功。之所以将Chrome放在第三判断,是因为我们预测Chrome很快会成为市场占有率第三的浏览器。其中,在分析浏览器版本时,用到了正则表达式来析取其中的版本信息。
& w4 W) s+ B+ ?* K' {0 S" @: w 如果你的JavaScript玩得很高,你还可以将前面的判断代码写成这样:
+ ^3 B7 w7 ]- P* O4 a! S. x
; J, G, }% j8 B! q8 n3 t0 O <script type="text/javascript">
. @5 x) l, W) z9 _* s$ n5 r var Sys = {};0 I% W6 Z9 |' G, i4 C3 ~4 K
var ua = navigator.userAgent.toLowerCase();
3 p4 N5 G; z& g7 C window.ActiveXObject ? Sys.ie = ua.match(/msie ([\d.]+)/)[1] :
, Z6 o7 l6 R8 A1 o# t- A document.getBoxObjectFor ? Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] :) m0 l Y8 b# B
window.MessageEvent && !document.getBoxObjectFor ? Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] :; s( A8 h" T5 X8 T4 y2 F
window.opera ? Sys.opera = ua.match(/opera.([\d.]+)/)[1] :
) \1 E9 ~ \7 ^ window.openDatabase ? Sys.safari = ua.match(/version\/([\d.]+)/)[1] : 0;! S( `* L7 c- \2 M6 f0 c
/ ]; x$ M+ H$ J //以下进行测试
+ r+ f0 d) V5 c& L; f) I0 Y, J if(Sys.ie) document.write('IE: '+Sys.ie);
) A2 u( K }3 A/ _ if(Sys.firefox) document.write('Firefox: '+Sys.firefox);
4 d) C9 ^. l i" x& Z. L if(Sys.chrome) document.write('Chrome: '+Sys.chrome);
: K0 b; v- l; q8 `. B if(Sys.opera) document.write('Opera: '+Sys.opera);
2 w3 h% [4 t2 f9 c& y if(Sys.safari) document.write('Safari: '+Sys.safari);2 t9 [1 c# Q W# d$ b
</script>4 ?4 w- {) ^# }: F
" y6 M Z2 @) q) J$ {
& k( |9 P, Y) Z0 p& M% j0 r8 ?: D7 Y; v! B9 w6 p
这样可以使JavaScript代码更精简些。当然,可读性稍差一些,就看你是重视效率还是重视可维护性了。7 P# x) a% F& f& y
- P8 r3 |6 C' k0 ^2 L+ N4 J! j2 z
使用不同特征来判断浏览器的方法,虽然在速度上比用正则表达式分析userAgent要来的快,不过这些特征可能会随浏览器版本而变化。比如,一种浏览器本来独有的特性取得了市场上的成功,其他浏览器也就可能跟着加入该特性,从而使该浏览器的独有特征消失,导致我们的判断失败。因此,相对比较保险的做法是通过解析userAgent中的特征来判断浏览器类型。何况,反正判断版本信息也需要解析浏览器的userAgent的。
6 K( g. Q7 T! j- I% G
, y& k7 |! X: @# H* @! s 通过分析各类浏览器的userAgent信息,不难得出分辨各类浏览器及其版本的正则表达式。而且,对浏览器类型的判断和版本的判断完全可以合为一体地进行。于是,我们可以写出下面的代码:2 T. }2 o: M, B. Y' [" i
; w+ `( Q1 y, C* \' Y2 F7 N) X<script type="text/javascript">% J5 S4 Y0 b% |! W& ]7 r4 g
var Sys = {};
+ ~2 k( b& @0 L0 Z/ X$ o" y1 @8 Y var ua = navigator.userAgent.toLowerCase();; G5 }' h2 ]5 ?6 C
var s;: `/ k% _2 W2 n6 \0 z
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
/ K7 k/ F3 O& S8 F) i; k (s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
' d; L" m$ o& x8 x8 q) r( B (s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
2 g* I$ l/ ^% F& u (s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :' E+ u& v/ @/ X7 t1 P
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;
2 [ G3 O/ v( @+ V" P: b
6 w' F' w4 ]) A& s* O //以下进行测试
! J' U0 m& k% V3 }, m if (Sys.ie) document.write('IE: ' + Sys.ie);! G% r! v6 L9 }5 `& @, F
if (Sys.firefox) document.write('Firefox: ' + Sys.firefox);4 n+ h& e: [. R, _
if (Sys.chrome) document.write('Chrome: ' + Sys.chrome);
" S: Q& C$ H* Y5 b if (Sys.opera) document.write('Opera: ' + Sys.opera);- P$ N! ~8 C9 R4 c0 j& T
if (Sys.safari) document.write('Safari: ' + Sys.safari);+ a: }% Q% g: a& K' i/ P! Z
</script>' [% S" f& C/ O9 u
5 E/ l7 f- Z* G$ r8 a \, |5 o8 p
2 H3 y0 u/ z6 d
其中,采用了“... ? ... : ...”这样的判断表达式来精简代码。判断条件是一条赋值语句,既完成正则表达式的匹配及结果复制,又直接作为条件判断。而随后的版本信息只需从前面的匹配结果中提取即可,这是非常高效的代码。; E- x, E2 I" ?# X- [7 V( I
以上的代码都是为了打造前端框架所做的预研,并在五大浏览器上测试通过。今后,判断某种浏览器只需用if(Sys.ie)或if(Sys.firefox)等形式,而判断浏览器版本只需用if(Sys.ie == '8.0')或if(Sys.firefox == '3.0')等形式,表达起来还是非常优雅的。- k' Y; i: x+ w! h0 b
9 y0 G: u ~$ c) C0 ] 前端框架项目已经启动,一切就看过程和结果了...
9 Z8 t; n; C8 ?$ ^5 X. {" p- Q3 H% g! t1 Z/ S( i7 [
|
|