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

資訊專欄INFORMATION COLUMN

我是怎么寫JavaScript框架的(一)

李世贊 / 276人閱讀

摘要:我就打算慢慢解析我是怎么寫的,并穿插講解我對(duì)版寫法的理解。其實(shí)源代碼里我都寫有注釋,我也是靠這些注釋回憶我當(dāng)時(shí)是怎么想的。把寫成,那就和的調(diào)用用法一樣。鏈?zhǔn)浇Y(jié)構(gòu)就是在每個(gè)方法結(jié)束時(shí)返回一個(gè)對(duì)象進(jìn)行下一個(gè)方法的操作。

前言

以前大三的時(shí)候?qū)懙囊粋€(gè)小框架,仿jquery鏈?zhǔn)浇Y(jié)構(gòu),純屬練手,大牛勿噴。當(dāng)時(shí)還把JQ的源碼全部打印下來(因?yàn)樵陔娔X上看不方便做筆記),7600+行代碼,300+頁A4紙,對(duì)照著看別人是怎么寫的。還好一個(gè)長我一屆的學(xué)長當(dāng)時(shí)比較閑,我說我想讀JQ代碼,他也沒讀過,就找來上兩屆的學(xué)長以前練手寫的小框架進(jìn)行學(xué)習(xí)。可惜只找到了壓縮混淆后的代碼,對(duì)于一個(gè)渣渣來說,閱讀起來很困難。在他的指點(diǎn)下,我大致了解了原理,并開始著手自己寫。現(xiàn)在陸續(xù)有學(xué)弟找我要這個(gè)代碼。雖然現(xiàn)在覺得寫得一塌糊涂,但是,可能對(duì)于和我當(dāng)時(shí)一樣摸不著邊的人來說,可能會(huì)有幫助。我就打算慢慢解析我是怎么寫的,并穿插講解我對(duì)JQ(2.0版)寫法的理解。其實(shí)源代碼里我都寫有注釋,我也是靠這些注釋回憶我當(dāng)時(shí)是怎么想的。可能會(huì)有很多不好的地方,輕噴~ 罒ω罒

我給庫起名Oct.js,是因?yàn)檫@個(gè)是在企鵝實(shí)習(xí)生應(yīng)聘失敗后為10月校招而寫。紀(jì)念那個(gè)稚嫩的我。

全部代碼,看這里看這里~( ̄▽ ̄)~* 
配合使用文檔看代碼更容易理解

閉包結(jié)構(gòu)

為了防止和別的庫的沖突,用閉包把整個(gè)框架安全地保護(hù)好。我們待會(huì)的代碼都寫在里面。這里創(chuàng)建一個(gè)全局變量"window.O",就是在window對(duì)象里加個(gè)O,它等價(jià)于 "Oct",相當(dāng)于jquery、Jquery這樣的別稱,意味著以后用Oct()或O()來進(jìn)行操作。把window.O寫成window.$,那就和JQ的$調(diào)用用法一樣。window.O返回一個(gè)Octobj對(duì)象,這很重要。

(function() {
    // 創(chuàng)建一個(gè)全局變量"window.O"
    window.O = Oct = function(selector, root_id, tag) { 
        return new Octobj(selector, root_id, tag); 
    }; 

    // 帥氣地定義一個(gè)版本
    Oct.version = "1.0"; 

})();
鏈?zhǔn)浇Y(jié)構(gòu)原理

JQ的流行,我想是因?yàn)樗芊奖惆桑粋€(gè)選擇器就可以接著寫一連串的方法。鏈?zhǔn)浇Y(jié)構(gòu)就是在每個(gè)方法結(jié)束時(shí)返回一個(gè)對(duì)象進(jìn)行下一個(gè)方法的操作。后面會(huì)通過代碼說明

選擇器

選擇器非常重要。JQ特別把選擇器部分剝離出一個(gè)庫sizzle.js。現(xiàn)在的JQ內(nèi)部也是調(diào)用JQ里面的sizzle。“選擇器”三個(gè)字寫得簡單,代碼寫起來就很有學(xué)問,sizzle.js這種高大上的我就不說了。我這里簡單實(shí)現(xiàn)一些功能:選擇class/id/標(biāo)簽。

首先,把上面的Octobj對(duì)象骨架搭建起來。包含selector, root_id, tag三個(gè)參數(shù)。selector就是你想要找的東西,root_id是你想要找的東西的上級(jí)的id,tag是你要指定返回某種標(biāo)簽。

var Octobj = function(selector, root_id, tag) {

};

定義一些參數(shù)

// args: 存儲(chǔ)root_id的子標(biāo)簽 
// type: 類型標(biāo)記,id("#"), class(".") 或者 tag("&。 tag也加標(biāo)記是為了代碼方便
// eles: 臨時(shí)的,存儲(chǔ)`selector`變量里"# . &"標(biāo)記后面的字符串
// selector_exp: 用來匹配標(biāo)簽的正則規(guī)則
var agrs, type, eles; 
var selector_exp = /^(?:#(w-_)+|.(w-_)+|(w)+)$/; 

// this.elements: 存儲(chǔ)函數(shù)結(jié)束后返回對(duì)象
this.elements = [];

// 防止以下情況: $(""), $(null), $(undefined), $(false)
if (!selector) {
    return this;
}

接下來處理有沒有指定root_id、tag的情況,

if (root_id) {
    root_id = typeof root_id == "string" ? document.getElementById(root_id) : root_id;
} else {
    root_id = document.body;
}
tag = tag || "*";
if (tag !== "*") {
    tag = tag.slice(1);
}

進(jìn)入核心部分。分兩種情況,能支持querySelector()方法的“高級(jí)”瀏覽器和不能支持的“低端”瀏覽器。先是能支持querySelector的,就很簡單了:

if (document.querySelectorAll) {
    // 因?yàn)槲矣?&"符號(hào)來標(biāo)記標(biāo)簽 ,所以要用"replace()"去掉"&" 
    var node_list = document.querySelectorAll(selector.replace("&", ""))
    for (var i in node_list) {
        if (node_list[i].tagName !== undefined) {
            // 把符合要求的元素存入`this.elements`
            this.elements.push(node_list[i]);
        }
    }
}

不能支持querySelector的,先來設(shè)置一些參數(shù):

// 處理類似JQ $(".a .b")的情況
selector = selector.replace(/^s+/, "").split(/s+/);

// 如果不指明 "root_id" 和 "tag", "args" 就存儲(chǔ)所有的標(biāo)簽
args = root_id.getElementsByTagName(tag);

// 通過符號(hào)標(biāo)記判斷是class/id/tag
type = selector[0].charAt(0);

// 所要選取的目標(biāo)的字符串
eles = selector[0].slice(1);  

處理選擇class的情況。有文章指出for in的效率不高,我本來是用for處理的,但是出現(xiàn)問題,因?yàn)闀?huì)把方法一起選進(jìn)來。JQ用了for in,感覺有了標(biāo)桿,我就全部改用for in了。

if (type === ".") {
    // 查找每個(gè)標(biāo)簽中有className,提取處理進(jìn)行匹配
    for (var i in args) {
        if(args[i].className) {

            // className 可能不止一個(gè), 通過空格進(jìn)行分割
            var r = args[i].className.split(/s+/);
            for (var j in r) {
                if (r[j] === eles) {
                    this.elements.push(args[i]);
                }
            }
        }
    }
}

處理選擇id的情況:

else if (type === "#") {
    for (var i in args) {
        if(args[i].id) {
            var r = args[i].id.split(/s+/);
            for (var j in r) {
                if (r[j] === eles) {
                    this.elements.push(args[i]);
                }
            }
        }
    }
}

處理選擇標(biāo)簽的情況:

else if (type === "&") {
    for (var i in args) {
        // 你可以"console.log(args[i]);" 可以看到最后一個(gè)是"length" ,沒有"tagName",所以要排除這個(gè)情況,否則會(huì)報(bào)錯(cuò)
        if (i !== "length" && typeof args[i] !== "function") {

            // "args[i].tagName" 在瀏覽器的屬性里是用大寫的,為了符合我的習(xí)慣,改用小寫進(jìn)行判斷
            if (args[i].tagName.toLowerCase() === eles.toLowerCase()) {
                this.elements.push(args[i]);
            }
        }
    }

}

基礎(chǔ)選擇器部分完成了,別忘了最后一句,返回找到的元素,給下一個(gè)方法進(jìn)行操作:

return this;

全部代碼

用法舉例

1.通過 id 選擇.

O("#buddy")

2.通過 class 選擇.

Oct(".buddy")

3.選擇所有 div.

O("&div") // also O("&Div"), O("&DIV")

4.選擇 .buddy 里的

.

O(".buddy", null, "&p")

5.選擇#dad下的.buddy

O(".buddy", "#dad")   

Laker"s blog

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

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

相關(guān)文章

  • 保姆級(jí)教程HTML兩萬字筆記大總結(jié)【建議收藏】(上篇)

    摘要:標(biāo)簽不區(qū)分大小寫,但推薦小寫。標(biāo)簽可以嵌套,但不能交叉嵌套。標(biāo)簽也稱為元素。比如行內(nèi)標(biāo)簽亦可成行內(nèi)元素。 ??HTML必備知識(shí)詳解?? 第一部分:HTML框架簡介...

    paulli3 評(píng)論0 收藏0
  • 在沒有DOM操作日子里,我是怎么熬過來(上)

    摘要:至于我為何要這么做,請(qǐng)聽閏土娓娓道來。那么接下來,正文從這開始熟悉閏土的朋友都知道,我是從時(shí)代過來的前端,在剛接觸和這類框架的時(shí)候,完全可以用一臉懵逼來形容我,最為貼切。作者閏土少年出處本博客的文章如無特殊說明,均為原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處。 showImg(https://segmentfault.com/img/bVZjKW?w=670&h=442); 前言 在我動(dòng)筆寫這篇文章的時(shí)候,...

    shuibo 評(píng)論0 收藏0
  • 我是如何從零開始學(xué)習(xí)前端

    摘要:相關(guān)頻道最后的坦白最后我得承認(rèn)這一次我又標(biāo)題黨了無非是想吸引更多前端初學(xué)者進(jìn)來,希望大家都能少走一些彎路,也希望那些從零開始自學(xué)前端的同學(xué)更有勇氣去面對(duì)自己的選擇。 我是怎么走上前端開發(fā)這條路? 首先,我是個(gè)文科生,大學(xué)里只學(xué)過vb,覺得計(jì)算機(jī)編程這東西太玄乎,不是我玩得轉(zhuǎn)的。 后來機(jī)緣巧合去做了一家互聯(lián)網(wǎng)創(chuàng)業(yè)公司的HR,閱了上千份程序員的簡歷,面了上百個(gè)不同水平不同領(lǐng)域的程序員。跟程...

    mykurisu 評(píng)論0 收藏0
  • 如何學(xué)JavaScript

    摘要:書籍如下面向?qū)ο缶幊讨改希L(fēng)格輕松易懂,比較適合初學(xué)者,原型那塊兒講得透徹,種繼承方式呢。還有另一件事情是,比如發(fā)現(xiàn)自己某個(gè)知識(shí)點(diǎn)不太清楚,可以單獨(dú)去百度。 作者:小不了鏈接:https://zhuanlan.zhihu.com/p/...來源:知乎著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 鑒于時(shí)不時(shí),有同學(xué)私信問我(老姚,下同)怎么學(xué)前端的問題。這里統(tǒng)一回...

    light 評(píng)論0 收藏0
  • 第三方庫

    摘要:微信支付,支付寶支付,銀聯(lián)支付三大支付總結(jié)支付寶植入總結(jié)支付寶的植基于和百度地圖的組件庫基于百度地圖封裝的組件庫,使用這個(gè)庫最好需要先了解和百度地圖。 Commento - 多說 & Disqus 開源替代品 Commento - 多說 & Disqus 開源替代品 anime.js 簡單入門教程 強(qiáng)大輕量的動(dòng)畫庫 anime.js 入門教程 來自B站的開源的MagicaSakura源...

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

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

0條評(píng)論

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