摘要:此模塊包含的設(shè)計(jì)思路即為預(yù)以匹配降級(jí)方案。沒(méi)有默認(rèn)編譯該模塊,以及利用該模塊判斷后提供平臺(tái)相關(guān)邏輯的主要原因在于其設(shè)計(jì)原則的代碼完成核心的功能。此處,也引出了代碼實(shí)現(xiàn)的另一個(gè)基本原則面向功能標(biāo)準(zhǔn),先功能覆蓋再優(yōu)雅降級(jí)。
在進(jìn)入 Zepto Core 模塊代碼之前,本節(jié)簡(jiǎn)略列舉 Zepto 及其他開(kāi)源庫(kù)中一些 Polyfill 的設(shè)計(jì)思路與實(shí)現(xiàn)技巧。
涉及模塊:IE/IOS 3/Detect.
IE 模塊 / CSSOM 相關(guān) PolyfillZepto 的 IE 模塊 src/ie.js 中僅僅包含了一個(gè)兼容性降級(jí)邏輯,雖簡(jiǎn)單其實(shí)現(xiàn)也值得學(xué)習(xí):
(function() { try { getComputedStyle(undefined); } catch (e) { var nativeGetComputedStyle = getComputedStyle; window.getComputedStyle = function(element, pseudoElement) { try { return nativeGetComputedStyle(element, pseudoElement); } catch (e) { return null; } }; } })();
低版本兼容模式(以 IE 7 為例)調(diào)用 getComputedStyle 會(huì)出現(xiàn)找不到該方法的問(wèn)題),已經(jīng)在高版本 IE 獲得支持:
The value of the property "getComputedStyle" is null or undefined, not a Function object
顧名思義該方法用于獲得元素的動(dòng)態(tài)計(jì)算屬性,此處在 windows 對(duì)象上顯式掛載包含 Failover 的 getComputedStyle 方法,使得該方法不存在時(shí)的調(diào)用代碼仍可繼續(xù)運(yùn)行,不行成阻塞。更詳細(xì)的多瀏覽器兼容方案可以通過(guò)閱讀 jQuery css API 源碼找到。
此模塊包含的設(shè)計(jì)思路即為Failover 預(yù) catch以匹配降級(jí)方案。
從該問(wèn)題中可以引申出一個(gè)常見(jiàn)問(wèn)題,CSSOM 的瀏覽器支持程度遠(yuǎn)遠(yuǎn)低于 DOM 的支持程度,W3C 對(duì)于 Document Object Model (DOM) Level 2 Style Specification 的聲明早已于 2000 年末時(shí)刻完成,然而 CSSOM 的官方標(biāo)準(zhǔn) CSS Object Model (CSSOM) 由于 CSS 3 多管道演進(jìn)的實(shí)現(xiàn)方式影響,仍未推出廠商公認(rèn)的實(shí)際標(biāo)準(zhǔn),因此對(duì)于 CSSOM 的操作設(shè)計(jì)與跨瀏覽器兼容性測(cè)試,jQuery 仍有極好的參考價(jià)值。同時(shí),開(kāi)源社區(qū)中也存在大量的 Polyfill(膩?zhàn)幽_本)用于對(duì)低版本瀏覽器通過(guò) JavaScript 附加邏輯的方式附加較新潮的特性,可以在 Modernizr/Modernizr 類似的代碼源中找到。閱讀 Polyfill 往往可以獲得對(duì) 原型鏈和 JS 面向?qū)ο?/strong>設(shè)計(jì)思維的更深刻認(rèn)識(shí),以及更深層次的設(shè)計(jì)技巧,以如下的一個(gè) IE 8 opacity 屬性的 Polyfill 函數(shù)為例,完成該函數(shù)的技巧已經(jīng)遠(yuǎn)遠(yuǎn)超越了自身實(shí)現(xiàn)的功能:
// 正則表達(dá)式,匹配滿足 alpha 定義規(guī)則的字符串 var opacityre = /s*alphas*(s*opacitys*=s*(d+)s*)/; // 原型鏈掛載,直接將 opacity 放入 CSSStyleDeclaration 中 defineProperty(window.CSSStyleDeclaration.prototype, "opacity", { // getter 函數(shù),自定義 toString 方法 get: function() { var m = this.filter.match(opacityre); return m ? (m[1] / 100).toString() : ""; }, // setter 函數(shù),將 opacity 值寫(xiě)入 alpha(opacity=$value) 的形式,供瀏覽器使用 set: function(value) { this.zoom = 1; var found = false; if (value < 1) { value = " alpha(opacity=" + Math.round(value * 100) + ")"; } else { value = ""; } this.filter = this.filter.replace(opacityre, function() { found = true; return value; }); if (!found && value) { this.filter += value; } } });
此腳本包含的設(shè)計(jì)思路為利用 Getter/Setter 控制不同上下文中屬性的設(shè)置與獲取,同樣的思路即為 Vue.js 數(shù)據(jù)綁定的設(shè)計(jì)源泉。
IOS 3 模塊 / 語(yǔ)言特性 PolyfillZepto 默認(rèn)編譯中未包含的 IOS 3 模塊 src/ios3.js 包含了兩個(gè)函數(shù)的兼容實(shí)現(xiàn),實(shí)際上屬于語(yǔ)言特性 Polyfill,這類 Polyfill 主要用于解決語(yǔ)言發(fā)展與實(shí)現(xiàn)不同步等問(wèn)題,并提供一些實(shí)現(xiàn)良好的公共方法用于業(yè)務(wù)開(kāi)發(fā),最常見(jiàn)的兩類例子:
Lodash / Underscore 提供大量實(shí)現(xiàn)良好的工具函數(shù)
TypeScript 提供類型系統(tǒng),實(shí)際這門(mén)語(yǔ)言也可被當(dāng)做 Polyfill 看,因?yàn)?ECMAScript 提案中,已經(jīng)包含了一個(gè)靜態(tài)類型系統(tǒng) 的建議
IOS 3 模塊中的兩個(gè) Polyfill 分別為 String / Array 兩個(gè)包裝類原型上掛載了一個(gè)常見(jiàn)方法:
// Line 6 String.prototype.trim = function() { // 將字符串首末的空格剪除 return this.replace(/^s+|s+$/g, ""); };
該方法原始定義于 ES 5 標(biāo)準(zhǔn)中的 String.prototype.trim(),此處實(shí)現(xiàn)依賴 ES 5 標(biāo)準(zhǔn)中的 White Space 中的描述。該方法實(shí)現(xiàn)相對(duì)簡(jiǎn)單,同時(shí)也提示了一個(gè)設(shè)計(jì)常識(shí):向公認(rèn)的 API 靠齊,實(shí)現(xiàn)方法核心后提供方法擴(kuò)展,遵循該原則的包括:
Preact 與 React
Zepto 與 jQuery
Lodash 與 Underscore 等
trim() 函數(shù)較為簡(jiǎn)單明確,而 reduce() 方法的實(shí)現(xiàn)與 ES 5 中的 Array.prototype.reduce(callbackfn[,initialValue]) 定義的算法完全相同,更能體現(xiàn)這一原則,此段不進(jìn)行注釋,進(jìn)入 ES 5 規(guī)范中該函數(shù)定義即可對(duì)照理解該 Polyfill 的實(shí)現(xiàn)方法。
// Line 11 if (Array.prototype.reduce === undefined) Array.prototype.reduce = function(fun) { // 略 };Detect 模塊 / User Agent 識(shí)別
Detect 模塊用于識(shí)別瀏覽器平臺(tái)類型,默認(rèn)也不處于編譯列表中,其代碼 src/detect.js 組織結(jié)構(gòu)如下:
// Line 5 ;(function($){ // 平臺(tái)偵測(cè)邏輯 function detect(ua, platform){ } // 傳入 Zepto 及平臺(tái)環(huán)境變量 detect.call($, navigator.userAgent, navigator.platform) // make available to unit tests $.__detect = detect // 將全局變量 Zepto 帶入,化為參數(shù) "$" })(Zepto)
平臺(tái)偵測(cè)邏輯 function detect(ua, platform) 內(nèi)部為一組大的字符串判斷邏輯,形成這樣雜亂無(wú)章的平臺(tái)判斷邏輯,正是因?yàn)橐淮淮臑g覽器大戰(zhàn)。 User-Agent 字符串被定義為包含了當(dāng)前瀏覽器(規(guī)范名稱 User Agent)信息的 HTTP 頭部標(biāo)識(shí),用于使服務(wù)器可以根據(jù)平臺(tái)完成瀏覽器檢測(cè)并下發(fā)不同的原始代碼用于渲染。由于瀏覽器偽裝等各種原因,UA 實(shí)際并不可信,因此對(duì)于它的偵測(cè)相當(dāng)困難,常見(jiàn) UA 可以從 List of User Agents 頁(yè)面內(nèi)查詢到。
Zepto 沒(méi)有默認(rèn)編譯該模塊,以及利用該模塊判斷后提供平臺(tái)相關(guān)邏輯的主要原因在于其設(shè)計(jì)原則:20% 的代碼完成 jQuery 核心 80% 的功能。此處,也引出了代碼實(shí)現(xiàn)的另一個(gè)基本原則:面向功能/API 標(biāo)準(zhǔn),先功能覆蓋再優(yōu)雅降級(jí)。以提供一個(gè)常見(jiàn)的 Browser Compatibility Matrix 為例,根據(jù)實(shí)現(xiàn)規(guī)格測(cè)試前端產(chǎn)出在不同平臺(tái)的可用性,再提供降級(jí)方案或 Polyfill 以滿足更多的用戶需求。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/108707.html
摘要:選擇的理由是一個(gè)用于現(xiàn)代瀏覽器的與大體兼容的庫(kù)。環(huán)境搭建分析環(huán)境的搭建僅需要一個(gè)常規(guī)頁(yè)面和原始代碼一個(gè)常規(guī)頁(yè)面打開(kāi)的首頁(yè)即可,在開(kāi)發(fā)人員工具中即可使用原始代碼本篇分析的代碼參照,進(jìn)入該代碼分支中即可。 選擇 Zepto 的理由 Zepto is a minimalist JavaScript library for modern browsers with a largely jQue...
摘要:本來(lái)想學(xué)習(xí)一下的源碼,但由于的源碼有多行,設(shè)計(jì)相當(dāng)復(fù)雜,所以決定從開(kāi)始,分析一個(gè)成熟的框架的代碼結(jié)構(gòu)及執(zhí)行步驟。同時(shí)發(fā)表在我的博客源碼分析代碼結(jié)構(gòu) 本來(lái)想學(xué)習(xí)一下jQuery的源碼,但由于jQuery的源碼有10000多行,設(shè)計(jì)相當(dāng)復(fù)雜,所以決定從zepto開(kāi)始,分析一個(gè)成熟的框架的代碼結(jié)構(gòu)及執(zhí)行步驟。 網(wǎng)上也有很多zepto的源碼分析,有的給源碼添加注釋,有的談與jQuery的不同,...
摘要:承接第一篇末尾內(nèi)容,本部分開(kāi)始進(jìn)入主模塊,分析其設(shè)計(jì)思路與實(shí)現(xiàn)技巧下文代碼均進(jìn)行過(guò)重格式化,但代碼版本同第一部分內(nèi)容且入口函數(shù)不變的選擇器先從第一個(gè)與原型鏈構(gòu)造不直接相關(guān)的工具函數(shù)說(shuō)起,觀察的設(shè)計(jì)思路。 承接第一篇末尾內(nèi)容,本部分開(kāi)始進(jìn)入 zepto 主模塊,分析其設(shè)計(jì)思路與實(shí)現(xiàn)技巧(下文代碼均進(jìn)行過(guò)重格式化,但代碼 Commit 版本同第一部分內(nèi)容且入口函數(shù)不變): Zepto 的選...
摘要:正則首先看一下其中的正則表達(dá)的正則表達(dá)式要包含在中間。后面可以跟來(lái)表示是否進(jìn)行全局匹配或者不區(qū)分大小寫(xiě)匹配。從句首開(kāi)始匹配是一個(gè),匹配一個(gè)空白字符,包括。 正則 首先看一下其中的正則表達(dá): fragmentRE = /^s*]*>/, singleTagRE = /^(?:|)$/, tagExpanderRE = /]*)/>/ig, rootNodeRE = /^(?:body|h...
摘要:源碼結(jié)構(gòu)整體結(jié)構(gòu)如果在編輯器中將的源碼折疊起來(lái),看到的就跟上面的代碼一樣。參考源碼分析代碼結(jié)構(gòu)對(duì)象思想與源碼分析設(shè)計(jì)和源碼分析源碼中關(guān)于的問(wèn)題最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注歡迎提意見(jiàn) 雖然最近工作中沒(méi)有怎么用 zepto ,但是據(jù)說(shuō) zepto 的源碼比較簡(jiǎn)單,而且網(wǎng)上的資料也比較多,所以我就挑了 zepto 下手,希望能為以后閱讀其他框架的源碼打下基礎(chǔ)吧。 源碼版...
閱讀 719·2021-08-17 10:15
閱讀 1826·2021-07-30 14:57
閱讀 2048·2019-08-30 15:55
閱讀 2880·2019-08-30 15:55
閱讀 2761·2019-08-30 15:44
閱讀 730·2019-08-30 14:13
閱讀 2443·2019-08-30 13:55
閱讀 2647·2019-08-26 13:56