出處:https://www.cnblogs.com/pengdai
二、S單一職責SRP
1、定義
2、原則分析
3、優(yōu)點
4、例子
三、O開放封閉原則OCP
1、定義
2、原則分析
3、例子
四、L里氏替換原則LSP
1、定義
2、原則分析
里氏代換原則是實現(xiàn)開閉原則的重要方式之一,由于使用基類對象的地方都可以使用子類對象,因此在程序中盡量使用基類類型來對對象進行定義,而在運行時再確定其子類類型,用子類對象來替換父類對象。
五、I接口隔離法則
1、定義
2、原則分析:
六、D依賴倒置原則DIP
1、定義
2、原則分析
3、例子1
[img]https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/ ... rFZQ/640?wx_fmt=png[/img]
七、合成/聚合復用原則
1、定義
2、原則分析
八、迪米特法則
1、定義
2、法則分析
5、例子
九、Q&A1、面向?qū)ο笤O計其他原則?
2、你能解釋一下里氏替換原則嗎?
3、什么情況下會違反迪米特法則?為什么會有這個問題?
4、給我一個符合開閉原則的設計模式的例子?
5、什么時候使用享元模式(蠅量模式)?
移動端推廣速度快,效果好,越來越多的企業(yè),商家開始重視移動站的建設和移動頁面(h5)的制作。隨著移動頁面的玩法越來越多,對前端技術(shù)的要求也會越來越高。
關(guān)于移動設備一些基本概念的理解。
網(wǎng)站示例
網(wǎng)址:https://github.com/amfe/lib-flexible;
1.Json的格式
其實json就是對象。源生的js代碼并沒有類的概念。對象救就是object。對象有自己的屬性,也可以有自己的方法。json是一種輕量級的存儲和交換信息的語言。他有自己的格式。
較為簡單的json。里面只有簡單的對象,key+value的形式:
每個元素之間用逗號隔開。調(diào)用每個key的值可用語句。例如:CellInfo.UEAmunt,就可取出其中的值。
較為復雜的json。里面包含了對象。
例如這個UEGroup1,里面的元素不僅有簡單的key+value,還包含了三個對象。對象里的元素用{}括起來,彼此之間用逗號隔開。想具體訪問某個元素的值也是通過逐層key,例如:UEGrooup1.DBR1.DLPackageSize
動態(tài)的往json只增加元素,增加對象。
前面說的幾個都是靜態(tài)的,提前寫好的。那如果臨時想加一個元素,例如在Cellinfo這個json中相加一個number的元素:
CellInfo.number=10;
對于往json中添加對象。例如我們想把Cellinfo和UEGroup1這兩個object作為兩個元素加入到另外一個大的json中:
2.json的發(fā)送
json寫好后,發(fā)送給后臺。至于后臺怎么處理數(shù)據(jù)我們不關(guān)心。發(fā)送json的函數(shù)如下:
}
參數(shù)分別是后臺的地址,變量,方法。變量就是我們自己寫好的json,方法默認為post。例如我們想發(fā)剛剛的PETInfo
$.post('http://10.140.160.64:3012/users/ueinfo', PETInfo);
數(shù)據(jù)的發(fā)送、并獲取結(jié)果的實例:
需求描述:用戶填寫一系列的輸入框,前端獲取數(shù)據(jù),封裝成json并發(fā)送給服務器,服務器會返回一個返回值,表示狀態(tài)。前端需要展示這個內(nèi)容提示客戶。
3.json在本地的存儲
存儲數(shù)據(jù)有很多方法。這里我用的是localStorage。localStorage與cookie的區(qū)別如下:
① cookie在瀏覽器與服務器之間來回傳遞。
sessionStorage和localStorage不會把數(shù)據(jù)發(fā)給服務器,僅在本地保存
②數(shù)據(jù)有效期不同:
cookie只在設置的cookie過期時間之前一直有效,即使窗口或瀏覽器關(guān)閉。
sessionStorage:僅在當前瀏覽器窗口關(guān)閉前有效。
localStorage 始終有效,長期保存。
③cookie數(shù)據(jù)還有路徑的概念,可以限制cookie只屬于某個路徑下。
存儲大小也不同,cookie數(shù)據(jù)不能超過4k,sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,可以達到5M或更大。
④ 作用域不用
sessionStorage不在不同的瀏覽器窗口中共享;
localStorage在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的;
WebStorage 支持事件通知機制,可以將數(shù)據(jù)更新的通知發(fā)送給監(jiān)聽者。Web Storage 的 api 接口使用更方便。
用localstage存儲json的實例:
將json取出來:
1.解決頁面使用overflow: scroll在iOS上滑動卡頓的問題?
首先你可能會給頁面的html和body增加了height: 100%, 然后就可能造成IOS上頁面滑動的卡頓問題。解決方案是:
(1) 看是否能把body和html的height: 100%去除掉。
(2) 在滾動的容器中增加:-webkit-overflow-scrolling: touch或者給body增加:body {overflow-x: hidden}。
2.ios頁面橡皮彈回效果遮擋頁面選項卡?
(1) 有時body和html的height: 100%去除掉問題可能就沒有了。
(2) 到達臨界值的時候在阻止事件默認行為
var startY,endY; //記錄手指觸摸的起點坐標 $('body').on('touchstart',function (e) { startY = e.touches[0].pageY; }); $('body').on('touchmove',function (e) { endY = e.touches[0].pageY; //記錄手指觸摸的移動中的坐標 //手指下滑,頁面到達頂端不能繼續(xù)下滑 if(endY>startY&& $(window).scrollTop()<=0){ e.preventDefault(); } //手指上滑,頁面到達底部能繼續(xù)上滑 if(endY<startY&& $(window).scrollTop()+ $(window).height()>=$('body')[0].scrollHeight){ e.preventDefault(); } })
有時也會碰見彈窗出來后兩個層的橡皮筋效果出現(xiàn)問題,我們可以在彈出彈出時給底層頁面加上一個類名,類名禁止頁面滑動這樣下層的橡皮筋效果就會被禁止,就不會影響彈窗層。 3.IOS機型margin屬性無效問題? (1) 設置html body的高度為百分比時,margin-bottom在safari里失效 (2) 直接padding代替margin 4.Ios綁定點擊事件不執(zhí)行? (1)添加樣式cursor :pointer。點擊后消除背景閃一下的css:-webkit-tap-highlight-color:transparent; 5.Ios鍵盤換行變?yōu)樗阉鳎?/span> 首先,input 要放在 form里面。 這時 "換行" 已經(jīng)變成 “前往”。 如果想變成 “搜索”,input 設置 type="search"。 6.Jq對a標簽點擊事件不生效? 出現(xiàn)這種情況的原因不明,有的朋友解釋:我們平時都是點擊的A標簽中的文字了。 所以要想用JS模擬點擊A標簽事件,就得先往A標簽中的文字添加能被JS捕獲的元素,然后再用JS模擬點擊該元素即可。但是我覺得不合理,雖然找不到原因但是解決辦法還是有的。 (1)document.getElementById("abc ").click(); (2)$("#abc ")[0].click(); 7.有時因為服務器或者別的原因?qū)е马撁嫔系膱D片沒有找到? 這是我們想需要用一個本地的圖片代替沒有找的的圖片
<script type="text/javascript"> function nofind(){ var img=event.srcElement; img.src="images/logoError.png"; img.onerror=null; 控制不要一直跳動 } </script> <img src="images/logo.png" />8.transform屬性影響position:fixed?
(1)規(guī)范中有規(guī)定:如果元素的transform值不為none,則該元素會生成包含塊和層疊上下文。CSS Transforms Module Level 1不只在手機上,電腦上也一樣。除了fixed元素會受影響之外,z-index(層疊上下文)值也會受影響。絕對定位元素等和包含塊有關(guān)的屬性都會受到影響。當然如果transform元素的display值為inline時又會有所不同。最簡單的解決方法就是transform元素內(nèi)部不能有absolute、fixed元素.
9.ios對position: fixed不太友好,有時我們需要加點處理?
在安卓上面,點擊頁面底部的輸入框,軟鍵盤彈出,頁面移動上移。
而ios上面,點擊頁面底部輸入框,軟鍵盤彈出,輸入框看不到了。。。查資料說什么的都有,iscroll,jquery-moblie,absolute,fixe,static都非常復雜,要改很多。。。
讓他彈出時讓滾動條在部
var u = navigator.userAgent, app = navigator.appVersion; var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端 if (isiOS) { $('textarea').focus(function () { window.setTimeout('scrollBottom()', 500); }); } function scrollBottom() { window.scrollTo(0, $('body').height()); }10.jq validate插件驗證問題?
(1)所以的input必須有name不然會出錯
11.有時手機會出現(xiàn)斷網(wǎng)的情況,我沒可能會對斷網(wǎng)的情況做一些處理?
(1)navigator.onLine可判斷是否是脫機狀態(tài).
12.判斷對象的長度?
(1)用Object.keys,Object.keys方法返回的是一個數(shù)組,數(shù)組里面裝的是對象的屬性
var person = { "name" : "zhangshan", "sex" : "man", "age" : "50", "height" : "180", "phone" : "1xxxxxxxxxx", "email" : "xxxxxxxxx@xxx.com" }; var arr = Object.keys(person); console.log(arr.length);(2)Object.getOwnPropertyNames(obj).length
13.上一題我們用到了Object.keys與Object.getOwnPropertyNames他們的區(qū)別?
Object.keys定義:返回一個對象可枚舉屬性的字符串數(shù)組;
Object.getOwnPropertyNames定義:返回一個對象可枚舉、不可枚舉屬性的名稱;
屬性的可枚舉性、不可枚舉性:定義:可枚舉屬性是指那些內(nèi)部 “可枚舉” 標志設置為 true 的屬性,對于通過直接的賦值和屬性初始化的屬性,該標識值默認為即為 true,對于通過 Object.defineProperty 等定義的屬性,該標識值默認為 false。
var obj = { "prop1": "v1" };
Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false });
console.log(Object.keys(obj).length); //output:1 console.log(Object.getOwnPropertyNames(obj).length); //output:2 console.log(Object.keys(obj)); //output:Array[1] => [0: "prop1"] console.log(Object.getOwnPropertyNames(obj)); //output:Array[2] => [0: "prop1", 1: "prop2"]
綜合實例
var obj = { "prop1": "v1" }; Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false}); console.log(obj.hasOwnProperty("prop1")); //output: true console.log(obj.hasOwnProperty("prop2")); //output: true console.log(obj.propertyIsEnumerable("prop1")); //output: true console.log(obj.propertyIsEnumerable("prop2")); //output: false console.log('prop1' in obj); //output: true console.log('prop2' in obj); //output: true for (var item in obj) { console.log(item); } //output:prop1 for (var item in Object.getOwnPropertyNames(obj)) { console.log(Object.getOwnPropertyNames(obj)[item]); } //ouput:[prop1,prop2]
14.移動開發(fā)不同手機彈出數(shù)字鍵盤問題?
(1)type="tel"
iOS和Android的鍵盤表現(xiàn)都差不多
(2)type="number"
優(yōu)點是Android下實現(xiàn)的一個真正的數(shù)字鍵盤
缺點一:iOS下不是九宮格鍵盤,輸入不方便
缺點二:舊版Android(包括微信所用的X5內(nèi)核)在輸入框后面會有超級雞肋的小尾巴,好在Android 4.4.4以后給去掉了。
不過對于缺點二,我們可以用webkit私有的偽元素給fix掉:
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
(3)pattern屬性
pattern用于驗證表單輸入的內(nèi)容,通常HTML5的type屬性,比如email、tel、number、data類、url等,已經(jīng)自帶了簡單的數(shù)據(jù)格式驗證功能了,加上pattern后,前端部分的驗證更加簡單了。
顯而易見,pattern的屬性值要用正則表達式。
實例 簡單的數(shù)字驗證
數(shù)字的驗證有兩個:
<input type="number" pattern="d">
<input type="number" pattern="[0-9]*">
15.input[number]類型輸入非數(shù)字字符
js獲取的值是空;比如-12,+123等
16.Javascript:history.go()和history.back()的用法與區(qū)別?
簡單的說就是:go(-1):返回上一頁,原頁面表單中的內(nèi)容會丟失;back():返回上一頁,原頁表表單中的內(nèi)容會保留。history.go(-1):后退+刷新history.back():后退
之所以注意到這個區(qū)別,是因為不同的瀏覽器后退行為也是有區(qū)別的,而區(qū)別就跟javascript:history.go()和history.back()的區(qū)別類似。
Chrome和ff瀏覽器后退頁面,會刷新后退的頁面,若有數(shù)據(jù)請求也會提交數(shù)據(jù)申請。類似于history.go(-1);
而safari(包括桌面版和ipad版)的后退按鈕則不會刷新頁面,也不會提交數(shù)據(jù)申請。類似于javascript:history.back();
17.Meta基礎知識:
<meta name="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
// width 設置viewport寬度,為一個正整數(shù),或字符串‘device-width’
// height 設置viewport高度,一般設置了寬度,會自動解析出高度,可以不用設置
// initial-scale 默認縮放比例,為一個數(shù)字,可以帶小數(shù)
// minimum-scale 允許用戶最小縮放比例,為一個數(shù)字,可以帶小數(shù)
// maximum-scale 允許用戶最大縮放比例,為一個數(shù)字,可以帶小數(shù)
// user-scalable 是否允許手動縮放
空白頁基本meta標簽
<!-- 設置縮放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
<!-- 可隱藏地址欄,僅針對IOS的Safari(注:IOS7.0版本以后,safari上已看不到效果) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 僅針對IOS的Safari頂端狀態(tài)條的樣式(可選default/black/black-translucent ) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- IOS中禁用將數(shù)字識別為電話號碼/忽略Android平臺中對郵箱地址的識別 -->
<meta name="format-detection"content="telephone=no, email=no" />
其他meta標簽
<!-- 啟用360瀏覽器的極速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 針對手持設備優(yōu)化,主要是針對一些老的不識別viewport的瀏覽器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微軟的老式瀏覽器 -->
<meta name="MobileOptimized" content="320">
<!-- uc強制豎屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ強制豎屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC強制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ強制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC應用模式 -->
<meta name="browsermode" content="application">
<!-- QQ應用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 點擊無高光 -->
<meta name="msapplication-tap-highlight" content="no">
18.移動端如何定義字體font-family?
@ --------------------------------------中文字體的英文名稱
@ 宋體 SimSun
@ 黑體 SimHei
@ 微信雅黑 Microsoft Yahei
@ 微軟正黑體 Microsoft JhengHei
@ 新宋體 NSimSun
@ 新細明體 MingLiU
@ 細明體 MingLiU
@ 標楷體 DFKai-SB
@ 仿宋 FangSong
@ 楷體 KaiTi
@ 仿宋_GB2312 FangSong_GB2312
@ 楷體_GB2312 KaiTi_GB2312
@
@ 說明:中文字體多數(shù)使用宋體、雅黑,英文用Helvetica
body { font-family: Microsoft Yahei,SimSun,Helvetica; }
19.打電話發(fā)短信寫郵件怎么實現(xiàn)?
// 一、打電話 <a href="tel:0755-10086">打電話給:0755-10086</a> // 二、發(fā)短信,winphone系統(tǒng)無效 <a href="sms:10086">發(fā)短信給: 10086</a> // 三、寫郵件 <a href="mailto:863139978@qq.com">點擊我發(fā)郵件</a> //2.收件地址后添加?cc=開頭,可添加抄送地址(Android存在兼容問題) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net">點擊我發(fā)郵件</a> //3.跟著抄送地址后,寫上&bcc=,可添加密件抄送地址(Android存在兼容問題) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net&bcc=384900096@qq.com">點擊我發(fā)郵件</a> //4.包含多個收件人、抄送、密件抄送人,用分號(;)隔開多個郵件人的地址 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]">點擊我發(fā)郵件</a> //5.包含主題,用?subject= <a href="mailto:863139978@qq.com?subject=郵件主題">點擊我發(fā)郵件</a> //6.包含內(nèi)容,用?body=;如內(nèi)容包含文本,使用%0A給文本換行 <a href="mailto:863139978@qq.com?body=郵件主題內(nèi)容%0A騰訊誠信%0A期待您的到來">點擊我發(fā)郵件</a> //7.內(nèi)容包含鏈接,含http(s)://等的文本自動轉(zhuǎn)化為鏈接 <a href="mailto:863139978@qq.com?body=http://www.baidu.com">點擊我發(fā)郵件</a> //8.內(nèi)容包含圖片(PC不支持) <a href="mailto:863139978@qq.com?body=<img src='images/1.jpg' />">點擊我發(fā)郵件</a> //9.完整示例 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]?cc=zhangqian0406@yeah.net&bcc=993233461@qq.com&subject=[郵件主題]&body=騰訊誠邀您參與%0A%0A[url=http://www.baidu.com]http://www.baidu.com[/url]%0A%0A<img src='images/1.jpg' />">點擊我發(fā)郵件</a>
|
素材類網(wǎng)站
Unsplash是一個分享免費高質(zhì)量照片的網(wǎng)站,照片分辨率都挺大,而且都是真實的攝影師作品,圖片多是風景和靜物:https://unsplash.com/
插件類網(wǎng)站
jq22,分享jQuery插件和提供各種jQuery的詳細使用方法,在線預覽,jQuery插件下載及教程:http://www.jq22.com/
http://www.htmleaf.com/ 這個網(wǎng)站與上一個網(wǎng)站類似,也提供了大量的jQuery插件。
layui,這是一個強大的模塊化前端框架:http://www.layui.com/
H-ui,端框架,一個輕量級前端框架,簡單免費,兼容性好,服務中國網(wǎng)站:http://www.h-ui.net/index.shtml
字體類網(wǎng)站
有字庫,一個免下載字體,直接在線引用字體的網(wǎng)站:http://www.youziku.com/onlinefont/index
PS字體庫,包含了幾乎所有類型的字體,下載好安裝,PS中就可以使用了:http://www.psjia.com/pssc/fontxz/list_18_3.html
圖標類網(wǎng)站
iconfont,這是阿里巴巴旗下的圖標庫網(wǎng)站,直接搜索關(guān)鍵詞就可以找到大批的圖標。下載圖標的時候我們還可以選擇顏色、大小、格式,根據(jù)自己的需要下載就好了:http://www.iconfont.cn/plus
easyicon,這也是一個非常有名的圖標庫,與上面那個不同的是,這里的圖標不是單一顏色的,而是設計好的顏色。下載圖標也很簡單,直接點擊對應圖標上面的格式就可以下載:http://www.easyicon.net/iconsearch/ios/
奧森圖標(Font Awesome),提供豐富的矢量字體圖標—通過CSS可以任意控制所有圖標的大小 ,顏色,陰影:http://www.thinkcmf.com/font/search.html
配色類網(wǎng)站
http://colorhunt.co,這個網(wǎng)站給我們提供了很多的配色方案,我們直接使用就OK了。
使用方法也很簡單,鼠標移動到對應的顏色上,我們就可以看到顏色的十六進制碼,復制這個顏色到工具里就可以使用了。
https://webgradients.com/, 180種漸變方案供你選擇,還可以直接復制CSS樣式應用到網(wǎng)頁中。
adobe,這個是Adobe公司出的,他提供了多種配色方案。我們點擊圓盤中間的點,就可以調(diào)整出我們想要的配色方案:https://color.adobe.com/zh/create/color-wheel
http://www.colorhunter.com/,這是一個提取現(xiàn)有圖片配色方案的工具。我們上傳一張圖片,它就會幫我們把圖片的配色提取出來供我們使用。
bootcss,這個網(wǎng)站是為WEB設計,開發(fā)中經(jīng)常用到的安全色。網(wǎng)站內(nèi)列出了顏色的十六進制碼和RGB碼,復制粘貼就可以了:http://www.bootcss.com/p/websafecolors/
sioe,這是一個在線RGB和十六進制顏色碼轉(zhuǎn)換工具。在對應的位置填入十六進制代碼,點擊轉(zhuǎn)換,我們就可以獲取到RGB顏色的代碼了:http://www.sioe.cn/yingyong/yanse-rgb-16/
‘==’和‘===’都是Javascript中的比較運算符,都是比較運算符兩邊是否相等。對于‘==’和‘===’的區(qū)別,大家也都知道:
‘==’僅僅是比較運算符兩邊的數(shù)值是否相等,如果數(shù)值相等則返回true;‘===’不僅會判斷運算符兩邊的數(shù)值是否相等,并且還會判斷兩邊的類型是否相等,只有數(shù)值和類型都相等才會返回true。雖然知道以上的判斷依據(jù)已經(jīng)能解決絕大數(shù)此類問題,但是如果往其中深究來說,會有同學問:在比較的時候‘===’先判斷類型,如果類型不同就直接返回false,這個沒什么問題。但是如果是‘==’比較兩個不同類型的數(shù)據(jù)時,具體是怎么進行計算判斷的呢?
既然是不同類型進行比較,肯定最終參與比較的結(jié)果必須是同一個類型的,因此JS會存在一個隱式轉(zhuǎn)換的問題,并且很多JS的隱式轉(zhuǎn)換很難通過console.log()等方法直觀的觀察到,因此很多初學者會對JS的隱式轉(zhuǎn)換感到疑惑。
首先讓我們回憶一下,咱們的JS中一共有哪些數(shù)據(jù)類型?
六大數(shù)據(jù)類型
基本數(shù)據(jù)類型(簡單數(shù)據(jù)類型)
number 數(shù)值型(NaN)
string 字符串
boolean 布爾型
undefined 未定義
null 空引用
引用數(shù)據(jù)類型(復雜數(shù)據(jù)類型)
object
JS基礎中,我們學習到咱們的JS中一共有六種數(shù)據(jù)類型,分為基本數(shù)據(jù)類型(簡單數(shù)據(jù)類型)和引用數(shù)據(jù)類型(復雜數(shù)據(jù)類型),不同類型的值進行比較的時候,存在隱式轉(zhuǎn)換的問題,咱們通過‘==’來驗證一下JS隱式轉(zhuǎn)換的情況。
1.我們首先來看看下列的語句計算結(jié)果:
console.log(NaN==true);//false
console.log(NaN==false);//false
console.log(NaN==0);//false
console.log(NaN==1);//false
console.log(NaN==NaN);//false
由上面的例子可以看出,NaN屬于Number數(shù)據(jù)類型中一個特殊情況,如果‘==’兩邊同為Number數(shù)據(jù)類型的數(shù)字,很直觀的可以看出值是否相同一眼就可以看出結(jié)果,但是作為Number類型的特殊情況,NaN在進行比較的時候,也會有特殊的結(jié)果:如果 x 或 y 中有一個為 NaN,則返回 false;
2.我們繼續(xù)看看下列的語句計算結(jié)果:
console.log(null == undefined); //true(特殊情況)---------------------------------
console.log(null == ''); //false
console.log(undefined == ''); //false
在上述例子中,引出了一個null,null是一個簡單數(shù)據(jù)類型,它的意義就是一個空應用,但是你如果通過console.log(typeof null) 來打印結(jié)果的時候卻發(fā)現(xiàn),結(jié)果竟然是object?此時你可能會懷疑人生,然后瘋狂的翻閱之前學習的資料,因為object明明是一個復雜數(shù)據(jù)類型,怎么會在判斷null這個簡單數(shù)據(jù)類型的類型時打印出來呢?其實,這個問題屬于一個歷史問題。咱們學習的JS在發(fā)展過程中是通過ECMAScript來確定規(guī)范的,每年都會有新的規(guī)定和規(guī)范提出,在JS的發(fā)展過程中,null一開始的作用就是用來指向一個空地址,讓開發(fā)者在創(chuàng)建數(shù)據(jù)的時候,先用null賦值給還未給值的對象用于標準初始化。但是其實咱們開發(fā)過程中很少用到,但是這個仍作為規(guī)范留了下來。又因為typeof是根據(jù)數(shù)據(jù)的前幾位判斷數(shù)據(jù)類型的,null相當于空指針,前幾位是地址的格式,所以判斷結(jié)果就為object。又因為undefined值是派生自null值的,因此ECMA-262規(guī)定對他們的相等測試要返回true。所以這一情況判斷的條件為:如果 x 與 y 皆為 null 或 undefined 中的一種類型,則返回 true(null == undefined // true);否則返回 false(null == 0 // false);
3.請看下列例子:
console.log(true == '123'); //false
console.log(true == '1'); //true
console.log(false == '0'); //true
console.log(true == !0); //true
console.log([] == []); //false
console.log([] == ![]); //true 比較地址 ------------------------------------------------
var a = c = [];
var b = [];
console.log(a == b); //false
console.log(a == !b); //true
console.log(a == c); //true
console.log(Boolean([]) == true); //true
console.log(Number([]) == 0); //true
console.log(Number(false) == 0); //true
其實比較的邏輯為:如果 x,y 類型不一致,且 x,y 為 String、Number、Boolean 中的某一類型,則將 x,y 使用 Number 函數(shù)轉(zhuǎn)化為 Number 類型再進行比較;
使用Number函數(shù)可以將其他的數(shù)據(jù)類型轉(zhuǎn)變?yōu)镹umber類型,這一同為Number類型的數(shù)據(jù),對比起來就會變得十分簡單。值得注意的是在上述的例子中,兩個空數(shù)組進行比較,結(jié)果返回的結(jié)果仍然為false,這個是怎么回事呢?其實這個很好理解,因為數(shù)組也是對象的一種,是復雜數(shù)據(jù)類型,所以用變量儲存對象時儲存的其實是地址。對象的內(nèi)容相同,但是儲存在堆區(qū)的位置不同,所以地址也是不同的,所以在判斷的時候返回的是false。
其實在JS中還有很多的隱式轉(zhuǎn)換情況,以上只是針對于‘==’的隱式轉(zhuǎn)換情況,對于這些問題,在實際開發(fā)過程中,需要作為開發(fā)者不斷的學習和積累,這也是咱們作為開發(fā)者的一個要求之一。
jquery是一個輕量級的JS框架,這點相信大部分人都聽過,而jquery之所以有這樣一個稱呼,就是因為它悄悄披了一件外衣,將自己給隱藏了起來。
/以下截取自jquery源碼片段
(function( window, undefined ) {
/* 源碼內(nèi)容 */
})( window );
上面這一小段代碼來自于1.9.0當中jquery的源碼,它是一個無污染的JS插件的標準寫法,專業(yè)名詞叫閉包??梢园阉唵蔚目醋鍪且粋€函數(shù),與普通函數(shù)不同的是,這個函數(shù)沒有名字,而且會立即執(zhí)行,就像下面這樣,會直接彈出字符串。
(function( window, undefined ) {
alert("Hello World!");
})( window );
可以看出來這樣寫的直接效果,就相當于我們直接彈出一個字符串。但是不同的是,我們將里面的變量變成了局域變量,這不僅可以提高運行速度,更重要的是我們在引用jquery的JS文件時,不會因為jquery當中的變量太多,而與其它的JS框架的變量命名產(chǎn)生沖突。對于這一點,我們拿以下這一小段代碼來說明。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
})( window );
alert(temp);
這段代碼的運行結(jié)果是Hello而不是ByeBye,也就是說閉包中的變量聲明沒有污染到外面的全局變量,倘若我們?nèi)サ糸]包,則最終的結(jié)果會是ByeBye,就像下面這樣。
var temp = "Hello World!";
// (function( window, undefined ) {
var temp = "ByeBye World!";
// })( window );
alert(temp);
由此就可以看出來,jquery的外衣就是這一層閉包,它是很重要的一個內(nèi)容,是編寫JS框架必須知道的知識,它可以幫助我們隱藏我們的臨時變量,降低污染。
剛才我們說了,jquery將自己聲明的變量全部都用外衣遮蓋起來了,而我們平時使用的Jquery和$,卻是真真實實的全局變量,這個是從何而來,謎底就在jquery的某一行代碼,一般是在文件的末尾。
window.jQuery = window.$ = jQuery;
這一句話將我們在閉包當中定義的jQuery對象導出為全局變量jQuery和$,因此我們才可以在外部直接使用jQuery和$。window是默認的JS上下文環(huán)境,因此將對象綁定到window上面,就相當于變成了傳統(tǒng)意義上的全局變量,就像下面這一小段代碼的效果一樣。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
window.temp = temp;
})( window );
alert(temp);
很明顯,它的結(jié)果應該是ByeBye,而不是Hello。因為我們在閉包中導出了temp局部變量為全局變量,從而覆蓋了第一行聲明的全局變量temp。
jquery最核心的功能,就是選擇器。而選擇器簡單理解的話,其實就是在DOM文檔中,尋找一個DOM對象的工具。
首先我們進入jquery源碼中,可以很容易的找到jquery對象的聲明,看過以后會發(fā)現(xiàn),原來我們的jquery對象就是init對象。
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery.fn = jQuery.prototype;
jQuery.fn.init.prototype = jQuery.fn;
這兩句話,第一句把jQuery對象的原型賦給了fn屬性,第二句把jQuery對象的原型又賦給了init對象的原型。也就是說,init對象和jQuery具有相同的原型,因此我們在上面返回的init對象,就與jQuery對象有一樣的屬性和方法。
很多時候,我們在jQuery和DOM對象之間切換時需要用到[0]這個屬性。從截圖也可以看出,jQuery對象其實主要就是把原生的DOM對象存在了[0]的位置,并給它加了一系列簡便的方法。這個索引0的屬性我們可以從一小段代碼簡單的看一下它的由來,下面是init方法中的一小段對DOMElement對象作為選擇器的源碼。
// Handle $(DOMElement)
if ( selector.nodeType ) {
/* 可以看到,這里將DOM對象賦給了jQuery對象的[0]這個位置 */
this.context = this[0] = selector;
this.length = 1;
return this;
}
這一小段代碼可以在jquery源碼中找到,它是處理傳入的選擇參數(shù)是一個DOM對象的情況??梢钥吹剑锩婧苊黠@的將jQuery對象索引0的位置以及context屬性,都賦予了DOM對象。代碼不僅說明了這一點,也同時說明了,我們使用$(DOMElement)可以將一個DOM對象轉(zhuǎn)換為jQuery對象,從而通過轉(zhuǎn)換獲得jQuery對象的簡便方法。
在我們的頁面布局的時候,經(jīng)常會有這樣的需求,超過指定行文本的時候會進行(省略號...)的處理,那么我們改怎么設置css呢?如下:
設置盒子的css為:
但是這樣只能顯示一行而不能實現(xiàn)指定行,所以還要其他的方法來實現(xiàn)指定行處理的。
WebKit瀏覽器或移動端的頁面(大部分移動端都是webkit)
css 代碼:
傳統(tǒng)方法的缺點:
傳統(tǒng)的web交互是用戶觸發(fā)一個http請求服務器,然后服務器收到之后,在做出響應到用戶,并且返回一個新的頁面,,每當服務器處理客戶端提交的請求時,客戶都只能空閑等待,并且哪怕只是一次很小的交互、只需從服務器端得到很簡單的一個數(shù)據(jù),都要返回一個完整的HTML頁,而用戶每次都要浪費時間和帶寬去重新讀取整個頁面。這個做法浪費了許多帶寬,由于每次應用的交互都需要向服務器發(fā)送請求,應用的響應時間就依賴于服務器的響應時間。這導致了用戶界面的響應比本地應用慢得多。
什么是ajax?
ajax的出現(xiàn),剛好解決了傳統(tǒng)方法的缺陷。AJAX 是一種用于創(chuàng)建快速動態(tài)網(wǎng)頁的技術(shù)。通過在后臺與服務器進行少量數(shù)據(jù)交換,AJAX 可以使網(wǎng)頁實現(xiàn)異步更新。這意味著可以在不重新加載整個網(wǎng)頁的情況下,對網(wǎng)頁的某部分進行更新。
XMLHttpRequest 對象
XMLHttpRequest對象是ajax的基礎,XMLHttpRequest 用于在后臺與服務器交換數(shù)據(jù)。這意味著可以在不重新加載整個網(wǎng)頁的情況下,對網(wǎng)頁的某部分進行更新。目前所有瀏覽器都支持XMLHttpRequest。
方法
|
描述
|
abort() |
停止當前請求 |
getAllResponseHeaders() |
把HTTP請求的所有響應首部作為鍵/值對返回 |
getResponseHeader("header") |
返回指定首部的串值 |
open("method","URL",[asyncFlag],["userName"],["password"]) |
建立對服務器的調(diào)用。method參數(shù)可以是GET、POST或PUT。url參數(shù)可以是相對URL或絕對URL。這個方法還包括3個可選的參數(shù),是否異步,用戶名,密碼 |
send(content) |
向服務器發(fā)送請求 |
setRequestHeader("header", "value") |
把指定首部設置為所提供的值。在設置任何首部之前必須先調(diào)用open()。設置header并和請求一起發(fā)送 ('post'方法一定要 ) |
1.創(chuàng)建XMLHTTPRequest對象
2.使用open方法設置和服務器的交互信息
3.設置發(fā)送的數(shù)據(jù),開始和服務器端交互
4.注冊事件
5.更新界面
下面給大家列出get請求和post請求的例子 :
get請求:
//步驟一:創(chuàng)建異步對象
var ajax = new XMLHttpRequest();
//步驟二:設置請求的url參數(shù),參數(shù)一是請求的類型,參數(shù)二是請求的url,可以帶參數(shù),動態(tài)的傳遞參數(shù)starName到服務端
ajax.open('get','getStar.php?starName='+name);
//步驟三:發(fā)送請求
ajax.send();
//步驟四:注冊事件 onreadystatechange 狀態(tài)改變就會調(diào)用
ajax.onreadystatechange = function () {
if (ajax.readyState==4 &&ajax.status==200) {
//步驟五 如果能夠進到這個判斷 說明 數(shù)據(jù) 完美的回來了,并且請求的頁面是存在的
console.log(xml.responseText);//輸入相應的內(nèi)容
}
}
post請求:
//創(chuàng)建異步對象
var xhr = new XMLHttpRequest();
//設置請求的類型及url
//post請求一定要添加請求頭才行不然會報錯
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.open('post', '02.post.php' );
//發(fā)送請求
xhr.send('name=fox&age=18');
xhr.onreadystatechange = function () {
// 這步為判斷服務器是否正確響應
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
為了方便使用,我們可以把他封裝進方法里面,要用的時候,直接調(diào)用就好了。
function ajax_method(url,data,method,success) {
// 異步對象
var ajax = new XMLHttpRequest();
// get 跟post 需要分別寫不同的代碼
if (method=='get') {
// get請求
if (data) {
// 如果有值
url+='?';
url+=data;
}else{
}
// 設置 方法 以及 url
ajax.open(method,url);
// send即可
ajax.send();
}else{
// post請求
// post請求 url 是不需要改變
ajax.open(method,url);
// 需要設置請求報文
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 判斷data send發(fā)送數(shù)據(jù)
if (data) {
// 如果有值 從send發(fā)送
ajax.send(data);
}else{
// 木有值 直接發(fā)送即可
ajax.send();
}
}
// 注冊事件
ajax.onreadystatechange = function () {
// 在事件中 獲取數(shù)據(jù) 并修改界面顯示
if (ajax.readyState==4&&ajax.status==200) {
// console.log(ajax.responseText);
// 將 數(shù)據(jù) 讓 外面可以使用
// return ajax.responseText;
// 當 onreadystatechange 調(diào)用時 說明 數(shù)據(jù)回來了
// ajax.responseText;
// 如果說 外面可以傳入一個 function 作為參數(shù) success
success(ajax.responseText);
}
}
}
去年谷歌和火狐針對WebVR提出了WebVR API的標準,顧名思義,WebVR即web + VR的體驗方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁,新的API標準讓我們可以使用js語言來開發(fā)。今天,約克先森將介紹如何開發(fā)一個WebVR網(wǎng)頁,在此之前,我們有必要了解WebVR的體驗方式。
WebVR體驗模式
WebVR的體驗方式可以分為VR模式和裸眼模式
一、VR模式
?滑配式HMD + 移動端瀏覽器
如使用cardboard眼鏡來體驗手機瀏覽器的webVR網(wǎng)頁,瀏覽器將根據(jù)水平陀螺儀的參數(shù)來獲取用戶的頭部傾斜和轉(zhuǎn)動的朝向,并告知頁面需要渲染哪一個朝向的場景。
?分離式HMD + PC端瀏覽器
通過佩戴Oculus Rift的分離式頭顯瀏覽連接在PC主機端的網(wǎng)頁,現(xiàn)支持WebVR API的瀏覽器主要是火狐的 Firefox Nightly和設置VR enabled的谷歌chrome beta。
二、裸眼模式
除了VR模式下的體驗方式,這里還考慮了裸眼下的體驗瀏覽網(wǎng)頁的方式,在PC端如果探測的用戶選擇進入VR模式,應讓用戶可以使用鼠標拖拽場景,而在智能手機上則應讓用戶可以使用touchmove或旋轉(zhuǎn)傾斜手機的方式來改變場景視角。
WebVR的概念大概就如此,這次我們將采用cardboard + mobile的方式來測試我們的WebVR場景,現(xiàn)在踏上我們的開發(fā)之旅。
準備工作
技術(shù)和框架:three.js for WebGL
Three.js是構(gòu)建3d場景的框架,它封裝了WebGL函數(shù),簡化了創(chuàng)建場景的代碼成本,利用three.js我們可以更優(yōu)雅地創(chuàng)建出三維場景和三維動畫。
測試工具:智能手機 + 滑配式頭顯
推薦使用cardboard或者某寶上三十塊錢的高仿貨。當然,如果你練就了裸眼就能將手機雙屏畫面看成單屏的能力也可以忽略。
需要引入的js插件:
webvr-polyfill.js
由于WebVR API還沒被各大主流瀏覽器支持,因此需要引入webvr-polyfill.js來支持WebVR網(wǎng)頁,它提供了大量VR相關(guān)的API,比如Navigator.getVRDevices()獲取VR頭顯信息的方法。
VRControls.js
VR控制器,是three.js的一個相機控制器對象,引入VRcontrols.js可以根據(jù)用戶在空間的朝向渲染場景,它通過調(diào)用WebVR API的orientation值控制camera的rotation屬性。
VREffect.js
VR分屏器,這是three.js的一個場景分屏的渲染器,提供戴上VR頭顯的顯示方式,VREffect.js重新創(chuàng)建了左右兩個相機,對場景做二次渲染,產(chǎn)生雙屏效果。
webvr-manager.js
這是WebVR的方案適配插件,它提供PC端和移動端的兩種適配方式,通過new WebVRManager()可以生成一個VR圖標,提供VR模式和裸眼模式的不同體驗,當用戶在移動端點擊按鈕進入VR模式時,WebVRManager便會調(diào)用VREffect分屏器進行分屏,而退出VR模式時,WebVRManager便用回renderer渲染器進行單屏渲染。
具體使用方法我們將在下文說明。
3D場景構(gòu)建
首先我們創(chuàng)建一個HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<title>webVR-helloworld</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
html,body {
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
</body>
<script src="./vendor/three.min.js"></script>
<script src="./vendor/webvr-polyfill.js"></script>
<script src="./vendor/VRControls.js"></script>
<script src="./vendor/VREffect.js"></script>
<script src="./vendor/webvr-manager.js"></script>
<script src="./main.js"></script>
</html>
接下來編寫js腳本,開始創(chuàng)建我們的3d場景。
1、創(chuàng)建場景
Three.js中的scene場景是繪制我們3d對象的整個容
1.var scene = new THREE.Scene();
2、添加相機
Three.js的相機
Three.js中的camera相機代表用戶的眼睛,我們通過設置FOV確定視野范圍,
3、添加渲染器
Three.js的渲染器用來渲染camera所看到的畫面
4、啟動動畫
產(chǎn)生動畫的原理就是讓camera持續(xù)連拍,同時每一次改變物體的屬性,通過requestAnimationFrame()方法遞歸的方式來持續(xù)更新場景對象屬性,你可以將它理解為setTimeout的優(yōu)化版。相比setTimeout函數(shù),requestAnimationFrame可以保證動畫渲染不會因為主線程的阻塞而造成跳幀。
至此,我們已經(jīng)繪制了一個簡單的3d場景并且讓它動了起來,接下來,我們需要讓我們的場景可以支持WebVR模式。
WebVR場景開發(fā)
WebVR網(wǎng)頁的基本原理其實是通過瀏覽器的WebVR API獲取用戶輸入,進而控制相機的視角,在VR模式下通過VR控制器和VR分屏器以二分屏+gyroscope(使用水平陀螺儀)的方式顯示畫面,裸眼情況下提供全屏+touchmove/gyroscope。
現(xiàn)在我們開始分別創(chuàng)建上文所說的VR控制器和VR分屏器
然后在前面創(chuàng)建的場景渲染函數(shù)里調(diào)用
至此,我們已經(jīng)完成了一個基本的webVR網(wǎng)頁,不過少了點交互效果好像,敬請期待Web開發(fā)的新世界---WebVR之交互事件。
完整代碼:在文章基礎上添加了天空和地面相關(guān)代碼,以及下篇文章將講到VR凝視交互事件。 demo演示地址 :手機瀏覽需設置允許橫屏。
結(jié)語
目前,國外的谷歌、火狐、Facebook和國內(nèi)百度已推出支持WebVR瀏覽器的版本,微軟也宣布將推出自己的VR瀏覽器,隨著后期5g網(wǎng)絡極速時代的到來以及HMD頭顯的價格和平臺的成熟,WebVR的體驗方式將是革命性的,用戶通過WebVR瀏覽網(wǎng)上商店,線上教學可進行“面對面”師生交流等,基于這種種應用場景,我們可以找到一個更好的動力去學習WebVR。
藍藍設計的小編 http://www.yvirxh.cn