这篇依然是跟 dom
相关的方法,侧重点是操作 dom
的方法。
读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto
源码版本
本文阅读的源码为 zepto1.2.0
.remove()
remove: function() {
return this.each(function() {
if (this.parentNode != null)
this.parentNode.removeChild(this)
})
},
删除当前集合中的元素。
如果父节点存在时,则用父节点的 removeChild
方法来删掉当前的元素。
相似方法生成器
zepto
中 after
、 prepend
、 before
、 append
、insertAfter
、 insertBefore
、 appendTo
和 prependTo
都是通过这个相似方法生成器生成的。
定义容器
adjacencyOperators = ['after', 'prepend', 'before', 'append']
首先,定义了一个相似操作的数组,注意数组里面只有 after
、 prepend
、 before
、 append
这几个方法名,后面会看到,在生成这几个方法后,insertAfter
、 insertBefore
、 appendTo
和 prependTo
会分别调用前面生成的几个方法。
辅助方法traverseNode
function traverseNode(node, fun) {
fun(node)
for (var i = 0, len = node.childNodes.length; i < len; i++)
traverseNode(node.childNodes[i], fun)
}
这个方法递归遍历 node
的子节点,将节点交由回调函数 fun
处理。这个辅助方法在后面会用到。
核心源码
adjacencyOperators.forEach(function(operator, operatorIndex) {
var inside = operatorIndex % 2 //=> prepend, append
$.fn[operator] = function() {
// arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
var argType, nodes = $.map(arguments, function(arg) {
var arr = []
argType = type(arg)
if (argType == "array") {
arg.forEach(function(el) {
if (el.nodeType !== undefined) return arr.push(el)
else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())
arr = arr.concat(zepto.fragment(el))
})
return arr
}
return argType == "object" || arg == null ?
arg : zepto.fragment(arg)
}),
parent, copyByClone = this.length > 1
if (nodes.length < 1) return this
return this.each(function(_, target) {
parent = inside ? target : target.parentNode
// convert all methods to a "before" operation
target = operatorIndex == 0 ? target.nextSibling :
operatorIndex == 1 ? target.firstChild :
operatorIndex == 2 ? target :
null
var parentInDocument = $.contains(document.documentElement, parent)
nodes.forEach(function(node) {
if (copyByClone) node = node.cloneNode(true)
else if (!parent) return $(node).remove()
parent.insertBefore(node, target)
if (parentInDocument) traverseNode(node, function(el) {
if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
(!el.type || el.type === 'text/javascript') && !el.src) {
var target = el.