Ruby's Louvre

每天学习一点点算法

导航

近似方法的实现

mass Framework使用了许多手段来一起生成近似方法,从而大大减少代码量,提高维护性。

比如append, prepend, before, after这几个方法,在jQuery2.0,它们是这个样子:

append: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		return this.domManip(arguments, false, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this );
			}
		});
	},

	after: function() {
		return this.domManip(arguments, false, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			}
		});
	},

mass Framework则是这样实现的,连反转方法也一并实现了。

            //前导 前置 追加 后放 替换
            "append,prepend,before,after,replace".replace($.rword, function(method) {
                $.fn[method] = function(item) {
                    return manipulate(this, method, item, this.ownerDocument);
                };
                $.fn[method + "To"] = function(item) {
                    $(item, this.ownerDocument)[method](this);
                    return this;
                };
            });

jQuery有三个移除节点的方法,2.0的实现如下:

// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		var elem,
			i = 0,
			l = this.length;

		for ( ; i < l; i++ ) {
			elem = this[ i ];

			if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( getAll( elem ) );
				}

				if ( elem.parentNode ) {
					if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
						setGlobalEval( getAll( elem, "script" ) );
					}
					elem.parentNode.removeChild( elem );
				}
			}
		}

		return this;
	},

	empty: function() {
		var elem,
			i = 0,
			l = this.length;

		for ( ; i < l; i++ ) {
			elem = this[ i ];

			if ( elem.nodeType === 1 ) {

				// Prevent memory leaks
				jQuery.cleanData( getAll( elem, false ) );

				// Remove any remaining nodes
				elem.textContent = "";
			}
		}

		return this;
	},
        detach: function( selector ) {
		return this.remove( selector, true );
	},

mass Framework则是一起放倒它们。

            "remove,empty,detach".replace($.rword, function(method) {
                $.fn[method] = function() {
                    var isRemove = method !== "empty";
                    for (var i = 0, node; node = this[i++]; ) {
                        if (node.nodeType === 1) {
                            //移除匹配元素
                            var array = $.slice(node[TAGS]("*")).concat(isRemove ? node : []);
                            if (method !== "detach") {
                                array.forEach(cleanNode);
                            }
                        }
                        if (isRemove) {
                            if (node.parentNode) {
                                node.parentNode.removeChild(node);
                            }
                        } else {
                            while (node.firstChild) {
                                node.removeChild(node.firstChild);
                            }
                        }
                    }
                    return this;
                }
            });

循环生成是艺术,需要深刻了解它们的功能与共同点,然后将特异点组成一个对象,这样方法内的if else就减到最小。

此外动态解析脚本也是个好办法,看mass Framework这段老代码:

 //淡入
     $.fn.fadeIn = function(duration, complete) {
        var opts = {
            duration: duration,
            complete: complete,
            effectName: "fadeIn",
            classRule: ".#{className}{\n\
                          #{prefix}animation-duration: #{duration};\
                          #{prefix}animation-name: #{frameName}; \
                          #{prefix}animation-fill-mode:forwards; \
                       }",
            frameRule: "@#{prefix}keyframes #{frameName}{\
                          to{\
                                opacity:1;\
                          }\
                       }",
            after: function(node) {
                node.style.opacity = 1;
            }
        }
        return makeEffect(this, opts);
    }
    //淡出
    $.fn.fadeOut = function(duration, complete) {
        var opts = {
            duration: duration,
            complete: complete,
            effectName: "fadeOut",
            classRule: ".#{className}{\n\
                          #{prefix}animation-duration: #{duration};\
                          #{prefix}animation-name: #{frameName}; \
                          #{prefix}animation-fill-mode:forwards; \
                       }",
            frameRule: "@#{prefix}keyframes #{frameName}{\
                          to{\
                                opacity:0;\
                          }\
                       }",
            after: function(node) {
                node.style.opacity = 0;
            }
        }
        return makeEffect(this, opts);
    }

这两个方法在源码上就只有两处不同,因此后来我改成这样:

     $.fn.fadeIn = function(duration, complete) {
        var opts = {
            duration: duration,
            complete: complete,
            effectName: "fadeIn",
            classRule: ".#{className}{\n\
                          #{prefix}animation-duration: #{duration};\
                          #{prefix}animation-name: #{frameName}; \
                          #{prefix}animation-fill-mode:forwards; \
                       }",
            frameRule: "@#{prefix}keyframes #{frameName}{\
                          to{\
                                opacity:1;\
                          }\
                       }",
            after: function(node) {
                node.style.opacity = 1;
            }
        }
        return makeEffect(this, opts);
    }
    //淡出
     $.fn.fadeOut = eval("0," + $.fn.fadeIn.toString().replace("1;","0;").replace("faceIn", "fadeOut"))

posted on 2013-03-26 09:23  司徒正美  阅读(1558)  评论(2编辑  收藏  举报