成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

如何實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的 jQuery

pumpkin9 / 3310人閱讀

摘要:對(duì)于操作來(lái)說(shuō),是非常方便的一個(gè)庫(kù),雖然如今隨著之類(lèi)框架的流行,用得越來(lái)越少了,但是其中很多思想還是非常值得我們學(xué)習(xí)的,這篇文章將介紹如何從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)化版。要實(shí)現(xiàn)類(lèi)似這樣的鏈?zhǔn)讲僮?,只需要在每個(gè)實(shí)例方法中返回一個(gè)即可。

對(duì)于操作 DOM 來(lái)說(shuō),jQuery 是非常方便的一個(gè)庫(kù),雖然如今隨著 React, Vue 之類(lèi)框架的流行,jQuery 用得越來(lái)越少了,但是其中很多思想還是非常值得我們學(xué)習(xí)的,這篇文章將介紹如何從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)化版 jQuery。

在這里,我把這個(gè)庫(kù)命名為 Clus(class 的諧音),下面以 $ 符號(hào)代替。

首先需要聲明一個(gè)構(gòu)造函數(shù)并做一些初始化操作:

function $(selector) {
    return new $.fn.init(selector);
}

$.fn = $.prototype = {
    contructor: $,
    init,
};

可以看到,該構(gòu)造函數(shù)返回一個(gè) $.fn.init 的實(shí)例,這樣做的好處就是在使用的時(shí)候不要每次都 new 一個(gè)構(gòu)造函數(shù)就可以創(chuàng)建一個(gè)新的實(shí)例了,可以看出來(lái),整個(gè)核心都在 init 函數(shù)上了:

function init(selector) {
    const fragmentRE = /^s*<(w+|!)[^>]*>/;
    const selectorType = $.type(selector);
    const elementTypes = [1, 9, 11];

    let dom;

    if (!selector) {
        dom = [],
        dom.selector = selector;
    } else if (elementTypes.indexOf(selector.nodeType) !== -1 || selector === window) {
        dom = [selector],
        selector = null;
    } else if (selectorType === "function") {
        return $(document).ready(selector);
    } else if (selectorType === "array") {
        dom = selector;
    } else if (selectorType === "object") {
        dom = [selector],
        selector = null;
    } else if (selectorType === "string") {
        if (selector[0] === "<" && fragmentRE.test(selector)) {
            dom = $.parseHTML(selector),
            selector = null;
        } else {
            dom = [].slice.call(document.querySelectorAll(selector));
        }
    }

    dom = dom || [];
    $.extend(dom, $.fn);
    dom.selector = selector;

    return dom;
}

可以很清楚的看到,根據(jù)傳入的參數(shù)類(lèi)型的不同進(jìn)行一些不同的操作,比如傳入的是函數(shù)的話(huà),則該函數(shù)里的操作的都是 DOM Ready 之后的操作了;再比如傳入的是字符串的話(huà),并且如果是標(biāo)簽的話(huà),則會(huì)把這段標(biāo)簽字符串解析成 DOM Fragment,如果是普通字符串,則會(huì)調(diào)用 document.querySelectorAll() 方法來(lái)查找 DOM。

相信大家都能很容易的看明白上面的代碼,不過(guò)有一點(diǎn)值得一提的是 $.extend(dom, $.fn); 這段代碼,其含義是把實(shí)例上的所有方法都添加到 dom 這個(gè)數(shù)組對(duì)象中,這樣做的目的就是為了可以直接鏈?zhǔn)秸{(diào)用某個(gè)實(shí)例的方法,比如 $(".clus").addClass("hello"),這個(gè) addClass() 方法就是在 $.fn 上實(shí)現(xiàn)的。因此所有在 $.fn 實(shí)現(xiàn)的方法都可以通過(guò) $(selector).method() 這種方式來(lái)調(diào)用了。

至于 extend() 方法我認(rèn)為是除了 init() 方法以外,整個(gè)庫(kù)中最核心的一個(gè)方法了,代碼如下:

export default function extend() {
    let options, name, clone, copy, source, copyIsArray,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    if (typeof target === "boolean") {
        deep = target;
        target = arguments[i] || {};
        i++;
    }

    if (typeof target !== "object" && $.type(target) !== "function") {
        target = {};
    }

    if (i === length) {
        target = this;
        i--;
    }

    for (; i < length; i++) {
        //
        if ((options = arguments[i]) !== null) {
            // for in source object
            for (name in options) {

                source = target[name];
                copy = options[name];

                if (target == copy) {
                    continue;
                }

                // deep clone
                if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
                    // if copy is array
                    if (copyIsArray) {
                        copyIsArray = false;
                        // if is not array, set it to array
                        clone = source && Array.isArray(source) ? source : [];
                    } else {
                        // if copy is not a object, set it to object
                        clone = source && $.isPlainObject(source) ? source : {};
                    }

                    target[name] = extend(deep, clone, copy);
                } else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
}

可以看到,和 jQuery 的實(shí)現(xiàn)一毛一樣,沒(méi)錯(cuò)就是從那兒 copy 過(guò)來(lái)的當(dāng)然一樣。

下面以 addClass() 方法為例介紹如何操作 DOM 的:

function addClass(cls) {
    let classes, clazz, el, cur, curValue, finalValue, j, i = 0;

    if (typeof cls === "string" && cls) {
        classes = cls.match(rnotwhite) || [];

        while((el = this[i++])) {
            curValue = getClass(el);
            cur = (el.nodeType === 1) && ` ${curValue} `.replace(rclass, " ");

            if (cur) {
                j = 0;

                while((clazz = classes[j++])) {
                    // to determine whether the class that to add has already existed
                    if (cur.indexOf(` ${clazz} `) == -1) {
                        cur += clazz + " ";
                    }
                    finalValue = $.trim(cur);
                    if ( curValue !== finalValue ) {
                        el.setAttribute("class", finalValue);
                    }
                }
            }
        }
    }

    return this;
}

$.fn.addClass = addClass;

值得一提的就是在實(shí)例方法中,this 關(guān)鍵字可以訪(fǎng)問(wèn)到根據(jù)選擇器所查詢(xún)到的所有元素的集合,在這里是通過(guò) while 循環(huán)來(lái)對(duì)每個(gè)元素進(jìn)行操作。要實(shí)現(xiàn)類(lèi)似 $(selector).addClass().removeClass() 這樣的鏈?zhǔn)讲僮鳎恍枰诿總€(gè)實(shí)例方法中返回一個(gè) this 即可。要實(shí)現(xiàn)其他實(shí)例方法比如 hasClass() 之類(lèi)的也是類(lèi)似的方法。

其實(shí)每個(gè)實(shí)例方法都是通過(guò) this 關(guān)鍵字來(lái)獲取查詢(xún)到的元素,然后遍歷這些元素來(lái)針對(duì)每個(gè)元素進(jìn)行具體的操作,在舉一個(gè)栗子:

function append(DOMString) {
    let el, i = 0,
        fregmentCollection = $.parseHTML(DOMString),
        fregments = Array.prototype.slice.apply(fregmentCollection);

    while((el = this[i++])) {
        fregments.map(fregment => {
            el.appendChild(fregment);
        });
    }

    return this;
}

$.fn.append = append;

上面是 append() 的實(shí)現(xiàn),首先先解析 DOMStringfregment,然后就是遍歷查詢(xún)到的元素(通過(guò) this 關(guān)鍵字)并針對(duì)每個(gè)元素去進(jìn)行 appendChild() 的操作,從而把 DOM 插入到匹配到的所有元素中。

其他實(shí)例方法也是通過(guò)類(lèi)似的方式實(shí)現(xiàn)的,這里就不一一細(xì)說(shuō)了,想更詳細(xì)的查看其他方法的實(shí)現(xiàn)可以直接到 Clus 中查看源碼。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100655.html

相關(guān)文章

  • 前端基礎(chǔ)進(jìn)階(十一):詳細(xì)圖解jQuery對(duì)象,以及如何擴(kuò)展jQuery插件

    摘要:而在構(gòu)造函數(shù)中,返回了的實(shí)例對(duì)象。在中直接返回過(guò)的實(shí)例,這里的是的真正構(gòu)造函數(shù)最后對(duì)外暴露入口時(shí),將字符與對(duì)等起來(lái)。因此當(dāng)我們直接使用創(chuàng)建一個(gè)對(duì)象時(shí),實(shí)際上是創(chuàng)建了一個(gè)的實(shí)例,這里的正真構(gòu)造函數(shù)是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早幾年學(xué)習(xí)前端,大家都非常熱衷于研究jQuery源...

    RebeccaZhong 評(píng)論0 收藏0
  • 2019 年了,為什么我還在用 jQuery?

    摘要:無(wú)論是還是,對(duì)許多應(yīng)用來(lái)說(shuō),這個(gè)大小都是完全可以接受的。但是為了不用,放棄向后兼容那我覺(jué)得還是用得了。自從年雙十一正式上線(xiàn),累計(jì)處理了億錯(cuò)誤事件,付費(fèi)客戶(hù)有金山軟件百姓網(wǎng)等眾多品牌企業(yè)。 譯者按: 看來(lái) jQuery 還是有一些用武之地的。 原文: Why Im Still Using jQuery in 2019 譯者: Fundebug 為了保證可讀性,本文采用意譯而非直譯...

    aikin 評(píng)論0 收藏0
  • ELSE 技術(shù)周刊(2017.11.27期)

    摘要:而且已開(kāi)源出來(lái),隨著容器技術(shù)發(fā)展,大文件分發(fā)一直是個(gè)重要的問(wèn)題,所以是一件值得研究的技術(shù)。實(shí)用推薦檢定攻略是近期推出的一項(xiàng)認(rèn)證,用以認(rèn)證開(kāi)發(fā)者的移動(dòng)網(wǎng)頁(yè)開(kāi)發(fā)技能。凈化,移除中不必要的文件技術(shù)周刊由小組出品,匯聚一周好文章,周刊原文。 業(yè)界動(dòng)態(tài) 直擊阿里雙11神秘技術(shù):PB級(jí)大規(guī)模文件分發(fā)系統(tǒng)蜻蜓 文章主要介紹了阿里的PB級(jí)大規(guī)模文件分發(fā)系統(tǒng)蜻蜓, 通過(guò)使用P2P技術(shù)同時(shí)結(jié)合智能壓縮、智...

    xushaojieaaa 評(píng)論0 收藏0
  • Java 程序員必備的 15 個(gè)框架,前 3 個(gè)地位無(wú)可動(dòng)搖!

    摘要:官網(wǎng)源碼推薦從開(kāi)始手寫(xiě)一個(gè)框架更多請(qǐng)?jiān)诩夹g(shù)棧微信公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字。是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)進(jìn)行了非常輕量級(jí)的對(duì)象封裝,它將與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的框架。 Java 程序員方向太多,且不說(shuō)移動(dòng)開(kāi)發(fā)、大數(shù)據(jù)、區(qū)塊鏈、人工智能這些,大部分 Java 程序員都是 Java Web/后端開(kāi)發(fā)。那作為一名 Java Web 開(kāi)發(fā)程序員必須需要熟悉哪些框架呢? 今天...

    galaxy_robot 評(píng)論0 收藏0
  • Jquery就是這么簡(jiǎn)單

    摘要:在內(nèi)部還是調(diào)用這些方法。對(duì)象下標(biāo),從開(kāi)始對(duì)象下標(biāo),從開(kāi)始再次重申對(duì)象只能調(diào)用對(duì)象的,對(duì)象只能調(diào)用對(duì)象的對(duì)象轉(zhuǎn)成值得注意的是在腳本內(nèi),是代表對(duì)象的。對(duì)象轉(zhuǎn)成對(duì)象語(yǔ)法也非常簡(jiǎn)單在內(nèi)寫(xiě)上對(duì)象,就變成了對(duì)象了。在文檔中對(duì)它的解釋是這樣子的。 什么是Jquery? Jquey就是一款跨主流瀏覽器的JavaScript庫(kù),簡(jiǎn)化JavaScript對(duì)HTML操作 就是封裝了JavaScript,能夠...

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

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

0條評(píng)論

pumpkin9

|高級(jí)講師

TA的文章

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