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

資訊專欄INFORMATION COLUMN

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

李世贊 / 280人閱讀

摘要:我就打算慢慢解析我是怎么寫的,并穿插講解我對版寫法的理解。其實源代碼里我都寫有注釋,我也是靠這些注釋回憶我當時是怎么想的。把寫成,那就和的調用用法一樣。鏈式結構就是在每個方法結束時返回一個對象進行下一個方法的操作。

前言

以前大三的時候寫的一個小框架,仿jquery鏈式結構,純屬練手,大牛勿噴。當時還把JQ的源碼全部打印下來(因為在電腦上看不方便做筆記),7600+行代碼,300+頁A4紙,對照著看別人是怎么寫的。還好一個長我一屆的學長當時比較閑,我說我想讀JQ代碼,他也沒讀過,就找來上兩屆的學長以前練手寫的小框架進行學習。可惜只找到了壓縮混淆后的代碼,對于一個渣渣來說,閱讀起來很困難。在他的指點下,我大致了解了原理,并開始著手自己寫。現在陸續有學弟找我要這個代碼。雖然現在覺得寫得一塌糊涂,但是,可能對于和我當時一樣摸不著邊的人來說,可能會有幫助。我就打算慢慢解析我是怎么寫的,并穿插講解我對JQ(2.0版)寫法的理解。其實源代碼里我都寫有注釋,我也是靠這些注釋回憶我當時是怎么想的。可能會有很多不好的地方,輕噴~ 罒ω罒

我給庫起名Oct.js,是因為這個是在企鵝實習生應聘失敗后為10月校招而寫。紀念那個稚嫩的我。

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

閉包結構

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

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

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

})();
鏈式結構原理

JQ的流行,我想是因為它很方便吧,一個選擇器就可以接著寫一連串的方法。鏈式結構就是在每個方法結束時返回一個對象進行下一個方法的操作。后面會通過代碼說明

選擇器

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

首先,把上面的Octobj對象骨架搭建起來。包含selector, root_id, tag三個參數。selector就是你想要找的東西,root_id是你想要找的東西的上級的id,tag是你要指定返回某種標簽。

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

};

定義一些參數

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

// this.elements: 存儲函數結束后返回對象
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);
}

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

if (document.querySelectorAll) {
    // 因為我用"&"符號來標記標簽 ,所以要用"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的,先來設置一些參數:

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

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

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

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

處理選擇class的情況。有文章指出for in的效率不高,我本來是用for處理的,但是出現問題,因為會把方法一起選進來。JQ用了for in,感覺有了標桿,我就全部改用for in了。

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

            // className 可能不止一個, 通過空格進行分割
            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]);
                }
            }
        }
    }
}

處理選擇標簽的情況:

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

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

}

基礎選擇器部分完成了,別忘了最后一句,返回找到的元素,給下一個方法進行操作:

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91446.html

相關文章

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

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

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

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

    shuibo 評論0 收藏0
  • 我是如何從零開始學習前端

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

    mykurisu 評論0 收藏0
  • 如何學JavaScript

    摘要:書籍如下面向對象編程指南,風格輕松易懂,比較適合初學者,原型那塊兒講得透徹,種繼承方式呢。還有另一件事情是,比如發現自己某個知識點不太清楚,可以單獨去百度。 作者:小不了鏈接:https://zhuanlan.zhihu.com/p/...來源:知乎著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 鑒于時不時,有同學私信問我(老姚,下同)怎么學前端的問題。這里統一回...

    light 評論0 收藏0
  • 第三方庫

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

    seanHai 評論0 收藏0

發表評論

0條評論

李世贊

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<