zepto源码研究 - zepto.js-3 (常用的工具)
pluck:
/** * 根据是否存在此属性来获取当前集合,返回一组属性值 * @param property * @returns {*} */ pluck: function(property){ return $.map(this, function(el){ return el[property] }) },
获取zepto对象的父节点时用到
filtered:
/** * 过滤,返回处理结果为true的记录 * @param selector * @returns {*} */ filter: function(selector){
/*
if(!selector) return this;
*/
//this.not(selector)取到需要排除的集合,第二次再取反(这个时候this.not的参数就是一个集合了),得到想要的集合 if (isFunction(selector)) return this.not(this.not(selector)) //filter收集返回结果为true的记录 return $(filter.call(this, function(element){ //当element与selector匹配,则收集 return zepto.matches(element, selector) })) }, /** * 在元素集中过滤某些元素 * @param nodes * @param selector * @returns {*|HTMLElement} */ function filtered(nodes, selector) { return selector == null ? $(nodes) : $(nodes).filter(selector) }
parent:
/** * 获取父元素 * @param selector * @returns {*|HTMLElement} */ parent: function(selector){ return filtered(uniq(this.pluck('parentNode')), selector) }
$.map:
/** * 内部方法 * 遍历对象/数组 在每个元素上执行回调,将回调的返回值放入一个新的数组返回 * @param elements * @param callback * @returns {*} */ $.map = function(elements, callback){ var value, values = [], i, key //如果被遍历的数据是数组或者Zepto(伪数组) if (likeArray(elements)) for (i = 0; i < elements.length; i++) { value = callback(elements[i], i)
// if (value != null) values.push(value) } else //如果是对象 for (key in elements) { value = callback(elements[key], key) if (value != null) values.push(value) } return flatten(values) }
parents:
/** * 取得所有匹配的祖先元素 * @param selector * @returns {*} */ parents: function(selector){ var ancestors = [], nodes = this //先取得所有祖先元素 while (nodes.length > 0) //到不再有父元素时,退出循环 //取得所有父元素 //nodes被再赋值为收集到的父元素数组 nodes = $.map(nodes, function(node){ //获取父级, isDocument(node) 到Document为止 // ancestors.indexOf(node)去重复 if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) { ancestors.push(node) //收集已经获取到的父级元素,用于去重复 return node } }) //筛选出符合selector的祖先元素 return filtered(ancestors, selector) },
这里的$.map还有过滤功能,callback若返回null或undefined,则映射值不会写入nodes数组中。这里的parents的调用者只能是单个dom的zepto集合,先是遍历将所有parentNode获取,然后根据selector调用filtered,选出满足条件的父节点。
children:
/** * 获取元素的子节集 * 原理:原生方法children 老的火狐不支持的,遍历childNodes * @param element * @returns {*} */ function children(element) { return 'children' in element ? slice.call(element.children) : $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node }) } /** * 获取子元素集 * @param selector * @returns {*|HTMLElement} */ children: function(selector){ return filtered(this.map(function(){ return children(this) }), selector) },
这里主要使用到了element.childNodes获取子节点,并用node.nodeType来剔除不等于1的
siblings:
/** * 获取兄弟节点集 * @param selector * @returns {*|HTMLElement} */ siblings: function(selector){ return filtered(this.map(function(i, el){ //到其父元素取得所有子节点,再排除本身 return filter.call(children(el.parentNode), function(child){ return child!==el }) }), selector) },
pre ,next:
/** * 筛选前面所有的兄弟元素 * @param selector * @returns {*} */ prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') }, /** * 筛选后面所有的兄弟元素 * @param selector * @returns {*} */ next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },