这篇依然是跟 dom
相关的方法,侧重点是操作 dom
的方法。
读Zepto源码系列文章已经放到了github上,欢迎star:
源码版本
本文阅读的源码为
.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.ownerDocument