乐趣区

jQuery之html()的实现

一、有这样一段 html
<div class=”divOne”>
<p> 嘿嘿嘿 </p>
</div>
<div class=”divOne”>
<p> 哈哈哈 </p>
</div>

二、jQuery 的 html() 方法
(1)当直接调用 $().html() 时,.html() 的作用是只读取第一个目标元素的 innerHTML
简单实现:
function customHtml(value) {
// 默认是选取第一个目标元素
let elem = this[0] || {},
i = 0,
l = this.length;
// 如果是 html(),即使读取目标元素的 innerHTML 的话
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}
//xxx
//xxx
}
(2)当调用 $().html(value) 时,.html() 的作用是为每一个符合条件的目标元素的 innerHTML 设置为 value
简单实现:
function customHtml(value) {
// 默认是选取第一个目标元素
let elem = this[0] || {},
i = 0,
l = this.length;
// 如果是 html(),即使读取目标元素的 innerHTML 的话
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}
// 根据目标元素的个数,依次对符合条件的目标元素赋值
for (; i < l; i++) {
elem = this[i] || {};
if (elem.nodeType === 1) {
elem.innerHTML = value;
}
}
}
(3)源码实现
源码:
// html() 方法设置或返回被选元素的内容(innerHTML)
// 当该方法用于返回内容时,则返回第一个匹配元素的内容
// 当该方法用于设置内容时,则重写所有匹配元素的内容
// http://www.runoob.com/jquery/html-html.html
// 源码 6203 行左右
function html(value) {
// 调用 $().html() 方法,即调用 access() 方法
// 关于 access() 方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
//access(this,function(),null,value,arguments.length)
return jQuery.access(this, function( value) {
// 读的话(.html())只读第一个匹配的目标元素的内容所以是 this[0]
// 写的话(.html(xxx))会循环每个匹配的目标并将其 innerHTML 置为 value
var elem = this[0] || {},
i = 0,
l = this.length;
// 当直接调用 html(),并且目标元素是元素节点时,$().html() 的本质是 selector.innerHTML
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}

// See if we can take a shortcut and just use innerHTML
// 如果能直接使用 innerHTML 来解析的话
// 注意:IE 的 innerHTML 会忽略开头的无作用域元素
if (typeof value === “string” &&
!rnoInnerhtml.test(value) &&
!wrapMap[( rtagName.exec( value) || [“”, “”] )[1].toLowerCase()] ) {
//Hello <b>world</b>!
value = jQuery.htmlPrefilter(value);
console.log(value,’value6235′)
try {
for (; i < l; i++) {
elem = this[i] || {};

// Remove element nodes and prevent memory leaks

if (elem.nodeType === 1) {
console.log(3333,’node6261′)
// getAll(elem, false): 获取原本 selector 内部的内容(标签)
// 先移除元素节点和注册的事件以防止内存泄漏
jQuery.cleanData(getAll( elem, false) );

elem.innerHTML = value;
}
}
// 将 elem 置为 0,是防止执行下面的 if(elem)…
elem = 0;

// If using innerHTML throws an exception, use the fallback method
} catch (e) {}
}

if (elem) {
this.empty().append( value)
}
}, null, value, arguments.length )
}
源码解析:
① 调用 html(),实际上是调用 access()
access 部分源码:
//$().html():access(this,function(),null,value,arguments.length)
// 源码 4051 行
// 关于 access() 方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
var access = function(elems, fn, key, value, chainable, emptyGet, raw) {
var i = 0,
//1
len = elems.length,
//true
bulk = key == null;

// Sets many values
if (toType( key) === “object” ) {
//xxx
} else if (value !== undefined) {
console.log(‘access->value!==undefined’,’value4053′)
chainable = true;
//xxx
if (bulk) {
// Bulk operations run against the entire set
// 走这边
if (raw) {
// 将 elems/selector,value 传入 function 并执行
// call(this,param)
fn.call(elems, value);
// 这里将 function 置为空值后,就不会执行 if(fn)… 了
fn = null;
// …except when executing function values
}
// 不走这边
else {
bulk = fn;
fn = function(elem, key, value) {
return bulk.call(jQuery( elem), value );
};
}
}
//xxx
//xxx
//xxx
};
也就是说:调用 jQuery.access() 相当于调用了 fn.call( elems, value),即自定义的方法 jQuery.access(this, function(value) {xxx})
② .html() 的情况调用这部分源码:
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}
③ .html(“ 字符串 ”)/.html(“<p> 这也是字符串 </p>”) 的情况调用这部分源码:
// See if we can take a shortcut and just use innerHTML
// 如果能直接使用 innerHTML 来解析的话
// 注意:IE 的 innerHTML 会忽略开头的无作用域元素
if (typeof value === “string” &&
!rnoInnerhtml.test(value) &&
!wrapMap[( rtagName.exec( value) || [“”, “”] )[1].toLowerCase()] ) {
//Hello <b>world</b>!
value = jQuery.htmlPrefilter(value);
console.log(value,’value6235′)
try {
for (; i < l; i++) {
elem = this[i] || {};
// Remove element nodes and prevent memory leaks
if (elem.nodeType === 1) {
console.log(3333,’node6261′)
// getAll(elem, false): 获取原本 selector 内部的内容(标签)
// 先移除元素节点和注册的事件以防止内存泄漏
jQuery.cleanData(getAll( elem, false) );
elem.innerHTML = value;
}
}
// 将 elem 置为 0,是防止执行下面的 if(elem)…
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch (e) {}
}
④ .html(这里面是标签) 的情况调用这部分源码:
标签:
let p=document.createElement(‘p’)
p.innerText=’ 哈哈哈 ’
$(“.divOne”).html(p)
源码:
if (elem) {
this.empty().append( value);
}
⑤ 总结 $(“.divOne”).html() 的本质即 $(“.divOne”)[0].innerHTML
$(“.divOne”).html(“Hello <b>world</b>!”) 的本质即 $(“.divOne”)[i].innerHTML=”Hello <b>world</b>!”
$(“.divOne”).html(标签) 的本质即 $(“.divOne”).empty().append( 标签)
源码:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>jQuery 之 html()</title>
</head>
<body>
<script src=”jQuery.js”></script>
<div class=”divOne”>
<p> 嘿嘿嘿 </p>
</div>
<div class=”divOne”>
<p> 嘿嘿嘿 </p>
</div>
<input type=”text” id=”inputOne”>
<script>
function customHtml(value) {
// 默认是选取第一个目标元素
let elem = this[0] || {},
i = 0,
l = this.length;
// 如果是 html(),即使读取目标元素的 innerHTML 的话
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}
// 根据目标元素的个数,依次对符合条件的目标元素赋值
for (; i < l; i++) {
elem = this[i] || {};
if (elem.nodeType === 1) {
elem.innerHTML = value;
}
}
}
// html() 方法设置或返回被选元素的内容(innerHTML)
// 当该方法用于返回内容时,则返回第一个匹配元素的内容
// 当该方法用于设置内容时,则重写所有匹配元素的内容
// http://www.runoob.com/jquery/html-html.html
// 源码 6203 行左右
function html(value) {
// 调用 $().html() 方法,即调用 access() 方法
// 关于 access() 方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
//access(this,function(),null,value,arguments.length)
return jQuery.access(this, function( value) {
// 读的话(.html())只读第一个匹配的目标元素的内容所以是 this[0]
// 写的话(.html(xxx))会循环每个匹配的目标并将其 innerHTML 置为 value
var elem = this[0] || {},
i = 0,
l = this.length;
// 当直接调用 html(),并且目标元素是元素节点时,$().html() 的本质是 selector.innerHTML
if (value === undefined && elem.nodeType === 1) {
return elem.innerHTML;
}

// See if we can take a shortcut and just use innerHTML
// 如果能直接使用 innerHTML 来解析的话
// 注意:IE 的 innerHTML 会忽略开头的无作用域元素
if (typeof value === “string” &&
!rnoInnerhtml.test(value) &&
!wrapMap[( rtagName.exec( value) || [“”, “”] )[1].toLowerCase()] ) {
//Hello <b>world</b>!
value = jQuery.htmlPrefilter(value);
console.log(value,’value6235′)
try {
for (; i < l; i++) {
elem = this[i] || {};

// Remove element nodes and prevent memory leaks

if (elem.nodeType === 1) {
console.log(3333,’node6261′)
// getAll(elem, false): 获取原本 selector 内部的内容(标签)
// 先移除元素节点和注册的事件以防止内存泄漏
jQuery.cleanData(getAll( elem, false) );

elem.innerHTML = value;
}
}
// 将 elem 置为 0,是防止执行下面的 if(elem)…
elem = 0;

// If using innerHTML throws an exception, use the fallback method
} catch (e) {}
}

if (elem) {
this.empty().append( value);
}
}, null, value, arguments.length );
}

customHtml.call(document.querySelectorAll(“.divOne”))
customHtml.call(document.querySelectorAll(“.divOne”),”Hello <b>world</b>!”)
// console.log($(“.divOne”).html())
// $(“.divOne”).html(“Hello <b>world</b>!”)
// let p=document.createElement(‘p’)
// p.innerText=’ 哈哈哈 gggg’
// $(“.divOne”).html(p)
// console.log(p,’p19′)
// $(“#divOne”).text(‘<p>aaaa</p>’)
// $(“#divOne”).text(p)

</script>
</body>
</html>

(完)

退出移动版