jq 核心逻辑
判断是否是 html 标签
js
/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;access
获取和设置集合值的多功能方法
本质是调用自己定义在属性上的方法
js
jQuery.fn.extend({
attr: function (name, value) {
return access(this, jQuery.attr, name, value, arguments.length > 1);
}
});在 access 中会传入 jQuery.attr,在内部会再调用这个函数
转驼峰
js
var rdashAlpha = /-([a-z])/g;
function fcamelCase(_all, letter) {
return letter.toUpperCase();
}
// Convert dashed to camelCase
function camelCase(string) {
return string.replace(rdashAlpha, fcamelCase);
}init
根据传入的参数创建并初始化 jQuery 对象
- 如果传入的参数是空、null、undefined 或 false,返回一个空的 jQuery 对象。
- 如果传入的参数是 DOM 元素,将该元素作为唯一元素添加到 jQuery 对象中。
- 如果传入的参数是函数,将该函数作为 DOMContentLoaded 事件的处理函数,等待文档加载完成后执行。
- 如果传入的参数是字符串:
- 如果是 HTML 字符串(以 < 开头且以 > 结尾),将解析该字符串并将生成的 DOM 元素添加到 jQuery 对象中。
- 如果是选择器字符串,使用相应的选择器引擎在文档中查找匹配的元素,并将它们添加到 jQuery 对象中。
- 否则,将传入的字符串作为 CSS 选择器,并使用相应的选择器引擎在文档中查找匹配的元素,并将它们添加到 jQuery 对象中。
- 如果传入的参数是 jQuery 对象,直接返回该对象。
- 其他情况,将传入的参数作为元素或元素数组添加到 jQuery 对象中。
isAttached
检查元素是否附加到文档中
js
jQuery.contains(elem.ownerDocument, elem) ||
elem.getRootNode(composed) === elem.ownerDocument;elem.ownerDocument元素所属的文档对象(Document 对象)elem.getRootNode根节点jQuery.contains用于替代原生的element.contains方法检查一个元素是否是另一个元素的后代。
js
contains: function( a, b ) {
var bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && (
// Support: IE 9 - 11+
// IE doesn't have `contains` on SVG.
a.contains ?
a.contains( bup ) :
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
) );
},a.contains(bup) 是 JavaScript 中的 DOM API,用于判断元素 a 是否包含元素 bup
前面的判断条件 a === bup 是为了处理特殊情况,即当 a 和 bup 是同一个元素时,直接返回 true,避免不必要的函数调用和比较操作,提高执行效率。
parseHTML
js
function( data, context, keepScripts ) {
var base, parsed, scripts;
if ( !context ) {
//创建一个空的 HTML 文档对象。
context = document.implementation.createHTMLDocument( "" );
// 在某些情况下,相对路径的解析可能会相对于当前文档的 URL,而不是相对于所期望的基本 URL。这可能导致加载资源或执行操作时出现问题,特别是涉及相对路径的链接、图像、样式表等。
//因此,通过设置基本 URL,可以确保解析后的元素在使用相对路径时具有正确的上下文,从而避免潜在的路径解析错误
base = context.createElement( "base" );
base.href = document.location.href;
context.head.appendChild( base );
}
// 判断是否是单标签
parsed = rsingleTag.exec( data );
scripts = !keepScripts && [];
// 单标签
if ( parsed ) {
return [ context.createElement( parsed[ 1 ] ) ];
}
parsed = buildFragment( [ data ], context, scripts );
// DOM 片段(DocumentFragment)中的所有子节点列表
return jQuery.merge( [], parsed.childNodes );
};内部会调用 buildFragment
创建一个临时的 <div> 元素(tmp)作为容器,并将 HTML 字符串赋值给 tmp 的 innerHTML 属性。这样会自动将 HTML 字符串解析为 DOM 元素并插入到 tmp 容器中。
parseXML
js
jQuery.parseXML = function (data) {
return new window.DOMParser().parseFromString(data, 'text/xml');
};使用示例
js
var xmlString = '<root><name>John</name><age>30</age></root>';
var xmlDoc = jQuery.parseXML(xmlString);
// 检查是否解析成功
if (xmlDoc) {
// 访问 XML 文档中的元素和属性
var rootElement = xmlDoc.documentElement;
var nameElement = rootElement.getElementsByTagName('name')[0];
var ageElement = rootElement.getElementsByTagName('age')[0];
var name = nameElement.textContent; // 获取文本内容
var age = ageElement.textContent;
console.log('Name: ' + name); // 输出: Name: John
console.log('Age: ' + age); // 输出: Age: 30
} else {
console.log('Invalid XML');
}ready
js
var readyList = jQuery.Deferred();
document.addEventListener('DOMContentLoaded', completed);
window.addEventListener('load', completed);类似 promise 的异步执行函数,早期,没有 promise 时 jq 自己实现的异步执行方法,为了兼容旧版本逻辑较为复杂,感兴趣可以这些去看一下源码
pushStack 在 jQuery 对象的堆栈上建立一个新的匹配元素集合
js
// 返回当前 jQuery 对象的构造函数的实例,相当于创建一个空的 jQuery 对象,然后使用 jQuery.merge() 将其中的元素合并
var ret = jQuery.merge(this.constructor(), elems);
//将原始的 jQuery 对象作为 ret 对象的 prevObject 属性
ret.prevObject = this;
return ret;cssHooks
hooks 是 jq 里面重要的设计思想,检测到需要 hook 处理的函数,就会执行 hook,vue 源码内也有类似内容