解密jQuery内核 DOM操作
jQuery针对DOM操作的插入的方法有大概10种
append、prepend、before、after、replaceWith
appendTo、prependTo、insertBefore、insertAfter、replaceAll
分2组,上下对照,实现同样的功能。主要的不同是语法——特别是内容和目标的位置
依赖的domManip,buildFragment模块在之前就分析过了
在匹配元素集合中的每个元素后面插入参数所指定的内容,作为其兄弟节点
对于 .after(), 选择表达式在函数的前面,参数是将要插入的内容。
对于.insertAfter(), 刚好相反,内容在方法前面,它将被放在参数里元素的后面。
after
after: function() {
return this.domManip( arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this.nextSibling );
}
});
},
之前提过了所有的方法靠this.domManip合并参数处理,内部通过buildFragment模块构建文档碎片
然后把每一个方法的具体执行通过回调的方式提供出来处理
DOM操作并未提供一个直接可以在当前节点后插入一个兄弟节点的方法,但是提供了一个类似的方法
insertBefore() 方法:可在已有的子节点前插入一个新的子节点。语法 :insertBefore(newchild,refchild)
看看jQuery如何处理的
例如
inner.after('<p>Test</p>');
内部就会把 '<p>Test</p>' 通过buildFragment构建出文档elem
然后通过 this.parentNode.insertBefore( elem, this.nextSibling );
这里的this 就是对应着inner ,elem就是‘<p>Test</p>’
看到这里就很好理解了after的实现了
用原生方法简单模拟
var inner = document.getElementsByClassName('inner')
for(var i =0 ; i<inner.length;i++){
var elem = inner[i]
var div = document.createElement('div')
div.innerHTML = 'aaaa'
elem.parentNode.insertBefore(div,elem.nextSibling)
}
insertAfter
jQuery代码的设计者很聪明的,都尽可能的合并相似功能的方法,代码更加精炼美观
jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function( name, original ) {
jQuery.fn[ name ] = function( selector ) {
};
});
DEMO
$('<p>Test</p>').insertAfter('.inner');
通过$('<p>Test</p>')构建一个文档,对象通过insertAfter方法插入到所有class等于inner的节点后
表达的意思与after是一样的,主要的不同是语法——特别是内容和目标的位置
jQuery.fn[ name ] = function( selector ) {
var elems,
ret = [],
insert = jQuery( selector ),
last = insert.length - 1,
i = 0;
for ( ; i <= last; i++ ) {
elems = i === last ? this : this.clone( true );
jQuery( insert[ i ] )[ original ]( elems );
// Support: QtWebKit
// .get() because core_push.apply(_, arraylike) throws
core_push.apply( ret, elems.get() );
}
return this.pushStack( ret );
};
看具体的实现方法中.insertAfter('.inner');inner其实就被当作selector传入进来了
selector可能只是字符串选择器内部就需要转化,insert = jQuery( selector ),
$('<p>Test</p>')就是构建出来的文档碎片节点,那么如果赋给insert有多个的时候就需要完全克隆一份副本了,所以就直接赋给
elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems );
依旧是执行after
jQuery( insert[ i ] )[ original ]( elems );
最终还需要返回这个构建的新节点
收集构建的节点
core_push.apply( ret, elems.get() );
构建一个新jQuery对象,以便实现链式
this.pushStack( ret );
可见after 与 insertAfter 本质本质其实都是一样的,只是通过不同的方式调用
before()
根据参数设定,在匹配元素的前面插入内容
before: function() {
return this.domManip( arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this );
}
});
},
类似after只是替换了第二个参数,改变插入的位置
append()
在每个匹配元素里面的末尾处插入参数内容
append: function() {
return this.domManip( arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.appendChild( elem );
}
});
},
内部增加节点,直接可以调用appendChild方法
prepend()
将参数内容插入到每个匹配元素的前面(元素内部)
prepend: function() {
return this.domManip( arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.insertBefore( elem, target.firstChild );
}
});
},
类似after只是替换了第二个参数,改变插入的位置
replaceWith()
用提供的内容替换集合中所有匹配的元素并且返回被删除元素的集合。
.replaceWith()可以从DOM中移除内容,然后在这个地方插入新的内容。请看下面的例子:
<div class="container">
<div class="inner first">Hello</div>
<div class="inner second">And</div>
<div class="inner third">Goodbye</div>
</div>
我们可以用指定的HTML替换第二个 inner <div> :
$('div.second').replaceWith('<h2>New heading</h2>');
结果如下:
<div class="container">
<div class="inner first">Hello</div>
<h2>New heading</h2>
<div class="inner third">Goodbye</div>
</div>
或者我们可以选择一个元素把它当做替换的内容:
$('div.third').replaceWith($('.first'));
结果如下:
<div class="container">
<div class="inner second">And</div>
<div class="inner first">Hello</div>
</div>
从这个例子可以看出,用来替换的元素从老地方移到新位置,而不是复制。
.replaceWith()方法,和大部分其他jQuery方法一样,返回jQuery对象,所以可以和其他方法链接使用,但是需要注意的是:对于该方法而言,该对象指向已经从 DOM 中被移除的对象,而不是指向替换用的对象。
replaceWith: function() {
var
// Snapshot the DOM in case .domManip sweeps something relevant into its fragment
args = jQuery.map( this, function( elem ) {
return [ elem.nextSibling, elem.parentNode ];
}),
i = 0;
// Make the changes, replacing each context element with the new content
this.domManip( arguments, function( elem ) {
var next = args[ i++ ],
parent = args[ i++ ];
if ( parent ) {
// Don't use the snapshot next if it has moved (#13810)
if ( next && next.parentNode !== parent ) {
next = this.nextSibling;
}
jQuery( this ).remove();
parent.insertBefore( elem, next );
}
// Allow new content to include elements from the context set
}, true );
// Force removal if there was no new content (e.g., from empty arguments)
return i ? this : this.remove();
},
删除目标节点
jQuery( this ).remove();
然后再插入一个新节点
parent.insertBefore( elem, next );
解密jQuery内核 DOM操作的更多相关文章
- 解密jQuery内核 DOM操作的核心函数domManip
domManip是什么 dom即Dom元素,Manip是Manipulate的缩写,连在一起就是Dom操作的意思. .domManip()是jQuery DOM操作的核心函数 对封装的节点操作做了参数 ...
- 解密jQuery内核 DOM操作的核心buildFragment
文档碎片是什么 http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-B63ED1A3 DocumentFragment is a & ...
- 解密jQuery内核 DOM操作方法(二)html,text,val
回顾下几组DOM插入有关的方法 innerHTML 设置或获取位于对象起始和结束标签内的 HTML outerHTML 设置或获取对象及其内容的 HTML 形式 看图对照区别 innerText 设置 ...
- 解密jQuery内核 样式操作
基础回顾 jQuery里节点样式读取以及设置都是通过.css()这个方法来实现的,本章通一下分解探究下jquery里这部分代码的实现 那么jQuery要处理样式的哪些问题? 先简单回顾下样式操作会遇到 ...
- jQuery的DOM操作详解
DOM(Document Object Model-文档对象模型):一种与浏览器, 平台, 语言无关的规则, 使用该接口可以轻松地访问页面中所有的标准组件DOM操作的分类 核心-DOM: DOM Co ...
- 第3章 jQuery的DOM操作
一. DOM 分为DOM核心,HTML-DOM和CSS-DOM 1.DOM核心 不专属与javascript. 获取对象:document.getElementsByTagName('div') 获 ...
- jQuery – 3.JQuery的Dom操作
3.1 JQuery的Dom操作 1.使用html()方法读取或者设置元素的innerHTML 2.使用text()方法读取或者设置元素的innerText 3.使用attr() ...
- js,jQuery和DOM操作的总结(二)
jQuery的基本操作 (1)遍历键值对和数组 , , , , , ]; $.map(arr, function (ele, index) { alert(ele + '===' + index); ...
- 03-老马jQuery教程-DOM操作
jQuery DOM操作 在没有jQuery之前,DOM的操作相对来说有点麻烦,尤其是DOM节点的搜索.目前我们已经学习了jQuery的选择器,接下带大家一块学习jQuery的DOM操作,jQuery ...
随机推荐
- unity3d UGUI多语言
从Foundation插件中抽离出的多语言.原理很简单,给Text绑定key,在程序开始时设置本地语言即可. 目录结构: LanguageEditor.cs:自定义编辑器: LanguageServi ...
- tornado 学习笔记16 HTTP1Connection
HTTP/1.x协议的具体实现.实现HTTPConnection接口. 16.1 构造函数 定义: def __init__(self, stream, is_client, params=None, ...
- MVC4 项目迁移 服务器被配置为不列出此目录的内容
前言: 将服务器中已经发布在IIS7上的网站,迁移到虚拟机中. 方便以后出现问题了,可以在自己的虚拟机中做测试提高工作效率. 问题: 迁移的6个MVC项目中有俩个碰到如下问题. 应用程序"T ...
- Files 的值“<<<<<<< .mine”无效。路径中具有非法字符
解决冲突,告诉SVN这个问题已解决(Resolved). 一般更简单些:在你的工程OBJ/DEBUG目录下,找到 工程名.csproj.FileListAbsolute.txt的文件打开并删除含有'& ...
- 基于webdriver的jmeter性能测试-通过jmeter实现jar录制脚本的性能测试
续接--基于webdriver的jmeter性能测试-Eclipse+Selenium+JUnit生成jar包 在进行测试前先将用于支持selenium录制脚本运行所需的类包jar文件放到jmeter ...
- C语言dll文件的说明以及生成、使用方法
最近在搞一些小项目,由于要涉及到跟其它语言进行交互,动态链接库变成了不二的选择.为此也查阅了很多资料,将动态链接库的相关知识在此做一个整理. 一.动态链接库概述 动态链接库(Dynamic Link ...
- PHP之几道面试题
1.二分查找算法 function two_find($arr,$low,$height,$k){ if($low<=$height){ $mid = intval(($low+$height) ...
- SageCRM 页面加载完后,用下拉框联动修改放大镜字段的取值范围
原理很简单就是修改放大镜属性中的sql. 函数如下:第一个参数是字段的名称.第二个参数是需要控制这个放大镜的sql.可以跟进下拉框的值来组织这个sql. /*--------------- For C ...
- CSS的定位
定位的基本思想:允许你定义元素框相对于其正常位置应该出现的位置,或者相对于父元素.另一个元素甚至浏览器窗口本身的位置 一切皆为框 div.h1 或 p 元素常常被称为块级元素 ...
- easyUI datagrid 根据查询条件 选中对应数据的行
开始 输入了 土豆,南瓜,再次是小青菜,每次输入点击搜索的时候(模糊查询),选中的当前数据对应的行 在做之前,在网上查询了许多资料,也在技术群里问过许多次,弄了好久终于好了. 第一次写博客真不知道写啥 ...