<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [toc] ## init 構造器 前面一講總體架構已經介紹了 jQuery 的基本情況,這一章主要來介紹 jQuery 的入口函數 jQuery.fn.init。 由于這個函數直接和 jQuery() 的參數有關,先來說下能接受什么樣的參數。源碼中接受 3 個參數: ``` init: function (selector, context, root) { ... } ``` - jQuery(),空參數,這個會直接返回一個空的 jQuery 對象,return this。 - jQuery( selector [, context ] ),這是一個標準且常用法,selector 表示一個 css 選擇器,這個選擇器通常是一個字符串,#id 或者 .class 等,context 表示選擇范圍,即限定作用,可為 DOM,jQuery 對象。 - jQuery( element|elements ),用于將一個 DOM 對象或 DOM 數組封裝成 jQuery 對象。 - jQuery( jQuery object|object ),會把普通的對象或 jQuery 對象包裝在 jQuery 對象中。 - jQuery( html [, ownerDocument ] ),這個方法用于將 html 字符串先轉成 DOM 對象后在生成 jQuery 對象。 - jQuery( html, attributes ),和上一個方法一樣,不過會將 attributes 中的方法和屬性綁定到生成的 html DOM 中,比如 class 等。 - jQuery( callback ),此方法接受一個回掉函數,相當于 window.onload 方法,只是相對于。 ## jQuery.fn.init 介紹完入口,就開始來看源碼。 ``` init: function (selector, context, root) { var match, elem; // 處理: $(""), $(null), $(undefined), $(false) if (!selector) { return this; } // rootjQuery = jQuery( document ); root = root || rootjQuery; // 處理 HTML 字符串情況,包括 $("<div>")、$("#id")、$(".class") if (typeof selector === "string") { //此部分拆分,留在后面講 // HANDLE: $(DOMElement) } else if (selector.nodeType) { this[0] = selector; this.length = 1; return this; // HANDLE: $(function) } else if (jQuery.isFunction(selector)) { return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present selector(jQuery); } return jQuery.makeArray(selector, this); } ``` 上面有幾點需要注意,`root = root || rootjQuery`;,這個參數在前面介紹用法的時候,就沒有提及,這個表示 document,默認的話是 rootjQuery,而 `rootjQuery = jQuery( document )`。 可以看出,對于處理 `$(DOMElement)`,直接是把 jQuery 當作一個數組,`this[0] = DOMElement`。其實,這要從 jQuery 的基本構造講起,我們完成一個` $('div.span') `之后,然后一個 jQuery 對象(this),其中會得到一組(一個)DOM 對象,jQuery 會把這組 DOM 對象當作數組元素添加過來,并給一個 length。后面就像一些鏈式函數操作的時候,若只能對一個 DOM 操作,比如 width、height,就只對第一個元素操作,若可以對多個 DOM 操作,則會對所有 DOM 進行操作,比如`css()`。 jQuery 大題思路如下,這是一個非常簡單點實現: ``` jQuery.prototype = { // 簡單點,假設此時 selector 用 querySelectorAll init: function(selector){ var ele = document.querySelectorAll(selector); // 把 this 當作數組,每一項都是 DOM 對象 for(var i = 0; i < ele.length; i++){ this[i] = ele[i]; } this.length = ele.length; return this; }, //css 若只有一個對象,則取其第一個 DOM 對象 //若 css 有兩個參數,則對每一個 DOM 對象都設置 css css : function(attr,val){ for(var i = 0; i < this.length; i++){ if(val == undefined){ if(typeof attr === 'object'){ for(var key in attr){ this.css(key, attr[key]); } }else if(typeof attr === 'string'){ return getComputedStyle(this[i])[attr]; } }else{ this[i].style[attr] = val; } } }, } ``` 所以對于 DOMElement 的處理,直接將 DOM 賦值給數組后,return this。 jQuery.makeArray 是一個綁定 數組的函數,和上面的原理一樣,后面會談到。 在介紹下面的內容之前,先來介紹一個 jQuery 中一個識別 Html 字符串的正則表達式, ``` var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/; rquickExpr.exec('<div>') //["<div>", "<div>", undefined] rquickExpr.exec('<div></div>') //["<div></div>", "<div></div>", undefined] rquickExpr.exec('#id') //["#id", undefined, "id"] rquickExpr.exec('.class') //null ``` 上面這一系列的正則表達式 exec,只是為了說明 rquickExpr 這個正則表達式執行后的結果,首先,如果匹配到,結果數組的長度是 3,如果匹配到 `<div>` 這種 html,數組的第三個元素是 underfined,如果匹配到 #id,數組的第二個元素是 underfined,如果匹配不到,則為 null。 另外還有一個正則表達式: ``` var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); rsingleTag.test('<div></div>') //true rsingleTag.test('<div ></div>') //true rsingleTag.test('<div class="cl"></div>') //false rsingleTag.test('<div></ddiv>') //false ``` 這個正則表達式主要是對 html 的字符串進行驗證,達到不出差錯的效果。在這里不多介紹 exec 和正則表達式了。 下面來看下重點的處理 HTMl 字符串的情況: ``` if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // 這個其實是強行構造了匹配 html 的情況的數組 match = [null, selector, null]; } else { match = rquickExpr.exec(selector); } // macth[1] 限定了 html,!context 對 #id 處理 if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { //排除 context 是 jQuery 對象情況 context = context instanceof jQuery ? context[0] : context; // jQuery.merge 是專門針對 jQuery 合并數組的方法 // jQuery.parseHTML 是針對 html 字符串轉換成 DOM 對象 jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true)); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // 此時的 match 非彼時的 match if (jQuery.isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; // 處理 match(1) 為 underfined 但 !context 的情況 } else { elem = document.getElementById(match[2]); if (elem) { // this[0] 返回一個標準的 jQuery 對象 this[0] = elem; this.length = 1; } return this; } // 處理一般的情況,find 實際上上 Sizzle,jQuery 已經將其包括進來,下章詳細介紹 // jQuery.find() 為 jQuery 的選擇器,性能良好 } else if (!context || context.jquery) { return (context || root).find(selector); // 處理 !context 情況 } else { // 這里 constructor 其實是 指向 jQuery 的 return this.constructor(context).find(selector); } ``` 關于 nodeType,這是 DOM 的一個屬性,詳情 Node.nodeType MDN。nodeType 的值一般是一個數字,比如 1 表示 DOM,3 表示文字等,也可以用這個值是否存在來判斷 DOM 元素,比如 context.nodeType。 整個 init 函數等構造邏輯,非常清晰,比如 (selector, context, root) 三個參數,分別表示選擇的內容,可能存在的的限制對象或 Object,而 root 則默認的 jQuery(document)。依舊采用 jQuery 常用的方式,對每一個變量的處理都非常的謹慎。 如果仔細看上面兩部分源代碼,我自己也加了注釋,應該可以把整個過程給弄懂。 find 函數實際上是 Sizzle,已經單獨出來一個項目,被在 jQuery 中直接使用,將在下章介紹 jQuery 中的 Sizzle 選擇器。通過源碼,可以發現: ``` jQuery.find = function Sizzle(){...} jQuery.fn.find = function(selector){ ... //引用 jQuery.find jQuery.find() ... } ``` ## 衍生的函數 init 函數仍然調用了不少 jQuery 或 jQuery.fn 的函數,下面來逐個分析。 ### jQuery.merge 這個函數通過名字,就知道它是用來干什么的,合并。 ``` jQuery.merge = function (first, second) { var len = +second.length, j = 0, i = first.length; for (; j < len; j++) { first[i++] = second[j]; } first.length = i; return first; } ``` 這樣子就可以對類似于數組且有 length 參數的類型進行合并,我感覺主要還是為了方便對 jQuery 對象的合并,因為 jQuery 對象就是有 length 的。 ### jQuery.parseHTML 這個函數也非常有意思,就是將一串 HTML 字符串轉成 DOM 對象。 首先函數接受三個參數,第一個參數 data 即為 html 字符串,第二個參數是 document 對象,但要考慮到瀏覽器的兼容性,第三個參數 keepScripts 是為了刪除節點里所有的 script tags,但在 parseHTML 里面沒有體現,主要還是給 buildFragment 當作參數。總之返回的對象,是一個 DOM 數組或空數組。 ``` jQuery.parseHTML = function (data, context, keepScripts) { if (typeof data !== "string") { return []; } // 平移參數 if (typeof context === "boolean") { keepScripts = context; context = false; } var base, parsed, scripts; if (!context) { // 下面這段話的意思就是在 context 缺失的情況下,建立一個 document 對象 if (support.createHTMLDocument) { context = document.implementation.createHTMLDocument(""); base = context.createElement("base"); base.href = document.location.href; context.head.appendChild(base); } else { context = document; } } // 用來解析 parsed,比如對 "<div></div>" 的處理結果 parsed:["<div></div>", "div"] // parsed[1] = "div" parsed = rsingleTag.exec(data); scripts = !keepScripts && []; // Single tag if (parsed) { return [context.createElement(parsed[1])]; } // 見下方解釋 parsed = buildFragment([data], context, scripts); if (scripts && scripts.length) { jQuery(scripts).remove(); } return jQuery.merge([], parsed.childNodes); } ``` buildFragment 函數主要是用來建立一個包含子節點的 fragment 對象,用于頻發操作的添加刪除節點。`parsed = buildFragment([data], context, scripts)`;建立好一個 fragment 對象,用 parsed.childNodes 來獲取這些 data 對應的 HTML。 ### jQueyr.makeArray jQuery 里面的函數調用,真的是一層接一層,雖然有時候光靠函數名,就能知道這函數的作用,但其中思考之邏輯還是挺參考意義的。 ``` jQuery.makeArray = function (arr, results) { var ret = results || []; if (arr != null) { if (isArrayLike(Object(arr))) { jQuery.merge(ret, typeof arr === "string" ? [arr] : arr); } else { push.call(ret, arr); } } return ret; } ``` makeArray 把左邊的數組或字符串并入到右邊的數組或一個新數組,其中又間接的引用 jQuery.merge 函數。 接下來是著 isArrayLike 函數,可能需要考慮多方面的因素,比如兼容瀏覽器等,就有了下面這一長串: ``` function isArrayLike(obj) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE var length = !!obj && "length" in obj && obj.length, type = jQuery.type(obj); if (type === "function" || jQuery.isWindow(obj)) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj; } ``` ## 總結 這篇算是承上啟下吧,介紹了 jQuery 中比較重要的入口函數,然后估計下章將會講解 Sizzle,jQuery 中的選擇器。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看