国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Zepto 源碼分析 1 - 進(jìn)入 Zepto

Aklman / 1955人閱讀

摘要:選擇的理由是一個(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 jQuery-compatible API. If you use jQuery, you already know how to use Zepto.

Zepto 是一個(gè)用于現(xiàn)代瀏覽器的與 jQuery 大體兼容的 JavaScript 庫(kù)。如果你使用過(guò) jQuery 的話,你已經(jīng)知道如何使用 Zepto 了。

Zepto.js 官方網(wǎng)對(duì)其進(jìn)行的描述簡(jiǎn)而言之即為一個(gè)大體兼容 jQuery 的 JavaScript 庫(kù),因此是否選擇分析 Zepto 這樣的庫(kù)前置問(wèn)題即為,對(duì)于此情此景下的前端入門者(2017 年的前端入行者,Like Me)是否還有分析 jQuery 源碼的必要?

我心中的答案,便是有也沒(méi)有,先說(shuō)沒(méi)有必要的一方面:

jQuery 包含大量針對(duì)“兩套標(biāo)準(zhǔn)”的兼容實(shí)現(xiàn),最明顯的例子即是對(duì) XHR 的處理方式上,因此對(duì)于類似的片段,尋找解決方案已經(jīng)沒(méi)有太大的意義:

var xhrSuccessStatus = {

        // File protocol always yields status code 0, assume 200
        0: 200,

        // Support: IE <=9 only
        // #1450: sometimes IE returns 1223 when it should be 204
        1223: 204
    },

jQuery 處理邏輯的基本對(duì)象基于 DOM,因此同時(shí)包含基礎(chǔ)庫(kù) Sizzle.js 用以實(shí)現(xiàn)純粹的跨平臺(tái)選擇器實(shí)現(xiàn),但由于 Document.querySelectorAll() 的兼容實(shí)現(xiàn)已經(jīng)覆蓋所有現(xiàn)代瀏覽器,類似這樣的判斷也沒(méi)有了太多的借鑒價(jià)值:

if ( support.qsa &&
    !nonnativeSelectorCache[ selector + " " ] &&
    (!rbuggyQSA || !rbuggyQSA.test( selector )) &&
    
    // Support: IE 8 only
    // Exclude object elements
    (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") )

-再說(shuō)有必要的一方面,仍然拿 querySelectorAll 舉例,Zepto 這一 jQuery 兼容庫(kù)中將其封裝為了如下的 qsa 函數(shù):

  zepto.qsa = function(element, selector) {
  // ...
      return element.getElementById && isSimple && maybeID
      ? (found = element.getElementById(nameOnly))
      // ...
      : slice.call(
          isSimple && !maybeID && element.getElementsByClassName
            ? maybeClass
              ? element.getElementsByClassName(nameOnly)
              : element.getElementsByTagName(selector)
            : element.querySelectorAll(selector)
        );
  };

即在調(diào)用該函數(shù)時(shí),根據(jù)類型先做出判斷,如果目標(biāo)為可識(shí)別的類型,那么采取相應(yīng)的方法進(jìn)行選擇,最終降級(jí)到使用 querySelectorAll() 這一函數(shù)進(jìn)行選擇。采用該方法的目的即為了盡可能的提高選擇器性能,參考 jsperf getElementById vs querySelector 的運(yùn)行結(jié)果便可略知一二:

測(cè)試調(diào)用 Ops / Sec Ops 差距
document.getElementById("foo") 27,869,670 fastest
document.querySelector("#foo") 11,206,845 62% slower
document.querySelector("[id=foo]") 11,281,576 59% slower

另一個(gè)例子,關(guān)于 jQuery 對(duì)象本質(zhì)的問(wèn)題,以簡(jiǎn)化的 Zepto 為例,其擁有如下多種的初始化方式:

$()
$(selector, [context])  ? collection
$()  ? same collection
$()  ? collection
$(htmlString)  ? collection
$(htmlString, attributes)  ? collection v1.0+
Zepto(function($){ ... }) 

而其調(diào)用生成的對(duì)象僅僅形似一個(gè)數(shù)組,但卻如何實(shí)現(xiàn)可以簡(jiǎn)單的操作 DOM 元素:

// 構(gòu)造一個(gè)空的 Zepto(Z) 對(duì)象
> $()

[selector: ""]
-> selector: ""
-> length: 0
-> __proto__: Object

// 選擇并著色
> $("p:last-child").css("background-color", "aliceblue")

答案便存在于 Zepto 的模塊結(jié)構(gòu)當(dāng)中,$.fn 包含暴露在外的工具函數(shù),當(dāng)一個(gè) Z 對(duì)象創(chuàng)建時(shí)將其設(shè)定為原型沒(méi),便可獲取其中的工具函數(shù):

zepto.Z.prototype = Z.prototype = $.fn;

這樣設(shè)計(jì)思想與實(shí)現(xiàn)方式的例子在 jQuery/Zepto 中比比皆是。面對(duì)有還是沒(méi)有必要閱讀 jQuery 源碼的問(wèn)題,比起 jQuery 中寫滿瀏覽器崢嶸歷史的長(zhǎng)篇巨著,Zepto 將其簡(jiǎn)化為了:

主體部分 1000 行的代碼規(guī)模

高度的 jQuery API 兼容

模塊化的組合方式,默認(rèn)編譯方式只包含現(xiàn)代瀏覽器支持

最大限度的降低了閱讀成本,因此該問(wèn)題的答案,可以回答為去粗取精,通過(guò)分析一種 jQuery 20% 代碼量的最簡(jiǎn)核心實(shí)現(xiàn)(Zepto),領(lǐng)略其 80% 的設(shè)計(jì)思想

環(huán)境搭建

Zepto 分析環(huán)境的搭建僅需要一個(gè)常規(guī)頁(yè)面原始代碼

一個(gè)常規(guī)頁(yè)面:打開(kāi) Zepto 的首頁(yè)即可,在開(kāi)發(fā)人員工具中即可使用 Zepto

原始代碼:本篇分析的 Zepto 代碼參照 Commit 3172e9,進(jìn)入該代碼分支中即可。

熱身部分,先從 Zepto 的模塊結(jié)構(gòu)開(kāi)始:

模塊結(jié)構(gòu)

Zepto 核心部分包含 zepto module 等五個(gè)默認(rèn)編譯入生產(chǎn)代碼的模塊,并且給出了擴(kuò)展插件的方法,那么第一個(gè)問(wèn)題便是,Zepto 是如何引入并提供模塊結(jié)構(gòu)的

進(jìn)入 package.json 發(fā)現(xiàn) Zepto 項(xiàng)目提供了三個(gè)公用的命令行入口,供 coffee-script 使用,實(shí)際入口為 make

    "scripts": {
        "test": "coffee make test",
        "dist": "coffee make dist",
        "start": "coffee test/server.coffee"
    },

進(jìn)入 make 文件,直接找到它生成 dist 的過(guò)程:

// Line 33
target.dist = ->
  target.build()
  target.minify()
  target.compress()

target.build = ->
  cd __dirname
  mkdir "-p", "dist"

  // 這里標(biāo)明了 5 個(gè)默認(rèn)的編譯模塊,可以通過(guò)環(huán)境變量改變編譯目標(biāo),且這些模塊名稱即為對(duì)應(yīng)的文件名
  modules = (env["MODULES"] || "zepto event ajax form ie").split(" ")
  module_files = ( "src/#{module}.js" for module in modules )
  
  // 聲明許可證,放在 dist 頭部,將目標(biāo)源碼文件中的注釋刪除,將 3 行以上的空行轉(zhuǎn)換為兩個(gè)空行寫入
  intro = "/* Zepto #{describe_version()} - #{modules.join(" ")} - zeptojs.com/license */
"
  dist = cat(module_files).replace(/^/[/*].*$/mg, "").replace(/
{3,}/g, "

")
  
  // 判斷是否將 AMD Layout 寫入,如果是,則將上文代碼填入 AMD 代碼段中,回報(bào)體積
  dist = cat("src/amd_layout.js").replace(/YIELD/, -> dist.trim()) unless env["NOAMD"]
  (intro + dist).to(zepto_js)
  report_size(zepto_js)

幾點(diǎn)額外的補(bǔ)充:

make 中的 #!/usr/bin/env coffee 是類 Unix 操作系統(tǒng)中表示文本文件解析器的聲明 Shebang),類似于 HTML 文檔的 DOCTYPE,該文件寫法可明顯看出 Linux Shell 腳本的意味,不過(guò)采用了 shelljs 這一運(yùn)行在 Nodejs 上的庫(kù)進(jìn)行了跨平臺(tái)。

make 中的 compress 過(guò)程中用到了 gzip 進(jìn)行壓縮: inp.pipe(gzip).pipe(out),該項(xiàng)壓縮對(duì)于用戶是透明的,用戶瀏覽器可以通過(guò) Content-Encoding HTTP 字段獲知該文件已被壓縮過(guò)并提供預(yù)解壓操作,詳見(jiàn) MDN - HTTP 協(xié)議中的數(shù)據(jù)壓縮。

make 腳本中還有很多的借鑒之處,例如 102 行 git 相關(guān)操作,以及 108 行開(kāi)始調(diào)用 uglify.js 進(jìn)行代碼壓縮的過(guò)程等,無(wú)論用 gruntwebpack 組織流水線也只是相似的工序,提供多個(gè)出口。

對(duì)于 src/amd_layout 這一沒(méi)被列入模塊列表中的文件,其作用即為兼容 AMD 標(biāo)準(zhǔn):

// src/amd_layout
// 作用于全局的 IIFE
(function(global, factory) {

  // AMD 兼容寫法
  if (typeof define === "function" && define.amd)
    define(function() { return factory(global) })
  else
    factory(global)
}(window, function(window) {

  // 如果包含 AMD 編譯,就將上文代碼完整寫入該函數(shù)
  YIELD
  return Zepto
}))

此模塊忽略 AMD 相關(guān)邏輯會(huì)得到一個(gè) JavaScript 庫(kù)中常見(jiàn)的立即執(zhí)行表達(dá)式(IIFE)結(jié)構(gòu),使用該結(jié)構(gòu)的目的即為構(gòu)造塊級(jí)作用域,防止庫(kù)中的變量對(duì)全局進(jìn)行污染,是一種非常常用的包裝方法,詳見(jiàn) MDN - IIFE:

(function(global, factory) {
  // ...
}(
  // ...
))
進(jìn)入 Zepto 主模塊

分析完 Zepto 模塊結(jié)構(gòu),開(kāi)始進(jìn)入 Zepto 主模塊,主模塊框架如下:

// src/zepto.js

// 將 Zepto 定義為一個(gè) IIFE
var Zepto = (function() {
  //... Zepto 內(nèi)部變量定義部分 6-47 行

  //... Zepto 內(nèi)部對(duì)象 zepto / 公共函數(shù)定義部分 48-167 行

  //... zepto/Z/$ 關(guān)系構(gòu)造
  zepto.Z =
  zepto.isZ =
  zepto.init =
  $ =
  extend =
  $.extend =
  
  //... 與 DOM 的橋梁 - querySelectorAll 實(shí)現(xiàn)
  zepto.qsa =
  
  // $ 對(duì)象對(duì)外的工具函數(shù) 279-404 行
  
  // 定義 $.fn,通過(guò)原型鏈賦予方法 
  $.fn = {
    constructor: zepto.Z,
    // ...
  }
  
  // 一些對(duì)于 $.fn 的其他函數(shù)實(shí)現(xiàn) 852-936 行
  
  // 繼續(xù)處理 zepto/Z/$ 的關(guān)系,將 Z 的原型指向 $.fn
  zepto.Z.prototype = Z.prototype = $.fn

  zepto.uniq = uniq
  zepto.deserializeValue = deserializeValue
  
  // 將內(nèi)置對(duì)象 zepto 掛載到 $ 對(duì)象
  $.zepto = zepto

  // 將 $ 作為 IIFE 返回值返回
  return $
})()

// 將 window.Zepto 指向 Zepto IIFE 的返回值 "$"
window.Zepto = Zepto

// 如果 "$" 還未被占用,就將其也初始為 Zepto IIFE 的返回值 "$"
window.$ === undefined && (window.$ = Zepto)

其核心設(shè)計(jì)思想即體現(xiàn)在 zepto/Z/$ 這三個(gè)組件之間的關(guān)系上,處理他們的關(guān)系也正是本篇的目的所在。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/108672.html

相關(guān)文章

  • Zepto 源碼分析 4 - 核心模塊入口

    摘要:對(duì)象構(gòu)造函數(shù)讀入的兩個(gè)參數(shù)與在中也有明確的規(guī)范,用以保證構(gòu)造函數(shù)的簡(jiǎn)單性。 承接第三篇末尾內(nèi)容,本篇結(jié)合官方 API 進(jìn)入對(duì) Zepto 核心的分析,開(kāi)始難度會(huì)比較大,需要重點(diǎn)理解幾個(gè)核心對(duì)象的關(guān)系,方能找到線索。 $() 與 Z 對(duì)象創(chuàng)建 Zepto Core API 的首個(gè)方法 $() 按照其官方解釋: Create a Zepto collection object by pe...

    xzavier 評(píng)論0 收藏0
  • Zepto 源碼分析 3 - qsa 實(shí)現(xiàn)與工具函數(shù)設(shè)計(jì)

    摘要:承接第一篇末尾內(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 的選...

    ctriptech 評(píng)論0 收藏0
  • Zepto源碼之Touch模塊

    摘要:在觸發(fā)事件前,先將保存定時(shí)器的變量釋放,如果對(duì)象中存在,則觸發(fā)事件,保存的是最后觸摸的時(shí)間。如果有觸發(fā)的定時(shí)器,清除定時(shí)器即可阻止事件的觸發(fā)。其實(shí)就是清除所有相關(guān)的定時(shí)器,最后將對(duì)象設(shè)置為。進(jìn)入時(shí),立刻清除定時(shí)器的執(zhí)行。 大家都知道,因?yàn)闅v史原因,移動(dòng)端上的點(diǎn)擊事件會(huì)有 300ms 左右的延遲,Zepto 的 touch 模塊解決的就是移動(dòng)端點(diǎn)擊延遲的問(wèn)題,同時(shí)也提供了滑動(dòng)的 swip...

    Prasanta 評(píng)論0 收藏0
  • Zepto 源碼分析 2 - Polyfill 設(shè)計(jì)

    摘要:此模塊包含的設(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/Dete...

    chuyao 評(píng)論0 收藏0
  • Zepto 源碼之神奇的 $

    摘要:返回值為,如果能查找到元素,則將元素以數(shù)組的形式返回,否則返回空數(shù)組排除不合法的。的第一個(gè)字符為,并且為標(biāo)簽。如果存在,則查找下選擇器為的所有子元素。正則表達(dá)式為如果沒(méi)有指定標(biāo)簽名,則獲取標(biāo)簽名。包裹元素的即為所需要獲取的。 經(jīng)過(guò)前面三章的鋪墊,這篇終于寫到了戲肉。在用 zepto 時(shí),肯定離不開(kāi)這個(gè)神奇的 $ 符號(hào),這篇文章將會(huì)看看 zepto 是如何實(shí)現(xiàn) $ 的。 讀Zepto源碼...

    xi4oh4o 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<