1. 程式人生 > >深入學習jquery原始碼之replaceWith()和replaceAll()

深入學習jquery原始碼之replaceWith()和replaceAll()

深入學習jquery原始碼之replaceWith()和replaceAll()

replaceWith(content|fn)

概述

將所有匹配的元素替換成指定的HTML或DOM元素。

引數

content String, Element, jQuery, Function

用於將匹配元素替換掉的內容。如果這裡傳遞一個函式進來的話,函式返回值必須是HTML字串。

fn Function

返回THML字串,用來替換的內容。

把所有的段落標記替換成加粗的標記。

<p>Hello</p><p>cruel</p><p>World</p>
$("p").replaceWith("<b>Paragraph. </b>");
<b>Paragraph. </b><b>Paragraph. </b><b>Paragraph. </b>

用第一段替換第三段,你可以發現他是移動到目標位置來替換,而不是複製一份來替換。

<div class="container">
  <div class="inner first">Hello</div>
  <div class="inner second">And</div>
  <div class="inner third">Goodbye</div>
</div>
$('.third').replaceWith($('.first'));
<div class="container">
  <div class="inner second">And</div>
  <div class="inner first">Hello</div>
</div>

 

replaceAll(selector)

概述

用匹配的元素替換掉所有 selector匹配到的元素。

在jQuery 1.3.2中,appendTo, prependTo, insertBefore, insertAfter, 和 replaceAll這個幾個方法成為一個破壞性操作,要選擇先前選中的元素,需要使用end()方法,參見 appendTo 方法的例二。

引數

selector 選擇器

用於查詢所要被替換的元素

把所有的段落標記替換成加粗標記

<p>Hello</p><p>cruel</p><p>World</p>
$("<b>Paragraph. </b>").replaceAll("p");
<b>Paragraph. </b><b>Paragraph. </b><b>Paragraph. </b>

 

jquery原始碼

    jQuery.each({
        appendTo: "append",
        prependTo: "prepend",
        insertBefore: "before",
        insertAfter: "after",
        replaceAll: "replaceWith"
    }, function (name, original) {
        jQuery.fn[name] = function (selector) {
            var elems,
                i = 0,
                ret = [],
                insert = jQuery(selector),
                last = insert.length - 1;

            for (; i <= last; i++) {
                elems = i === last ? this : this.clone(true);
                jQuery(insert[i])[original](elems);

                // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
                push.apply(ret, elems.get());
            }

            return this.pushStack(ret);
        };
    });
	
	    jQuery.fn.extend({
        replaceWith: function () {
            var arg = arguments[0];

            // Make the changes, replacing each context element with the new content
            this.domManip(arguments, function (elem) {
                arg = this.parentNode;

                jQuery.cleanData(getAll(this));

                if (arg) {
                    arg.replaceChild(elem, this);
                }
            });

            // Force removal if there was no new content (e.g., from empty arguments)
            return arg && (arg.length || arg.nodeType) ? this : this.remove();
        },
        domManip: function (args, callback) {

            // Flatten any nested arrays
            args = concat.apply([], args);

            var first, node, hasScripts,
                scripts, doc, fragment,
                i = 0,
                l = this.length,
                set = this,
                iNoClone = l - 1,
                value = args[0],
                isFunction = jQuery.isFunction(value);

            // We can't cloneNode fragments that contain checked, in WebKit
            if (isFunction ||
            (l > 1 && typeof value === "string" &&
                !support.checkClone && rchecked.test(value))) {
                return this.each(function (index) {
                    var self = set.eq(index);
                    if (isFunction) {
                        args[0] = value.call(this, index, self.html());
                    }
                    self.domManip(args, callback);
                });
            }

            if (l) {
                fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this);
                first = fragment.firstChild;

                if (fragment.childNodes.length === 1) {
                    fragment = first;
                }

                if (first) {
                    scripts = jQuery.map(getAll(fragment, "script"), disableScript);
                    hasScripts = scripts.length;

                    // Use the original fragment for the last item instead of the first because it can end up
                    // being emptied incorrectly in certain situations (#8070).
                    for (; i < l; i++) {
                        node = fragment;

                        if (i !== iNoClone) {
                            node = jQuery.clone(node, true, true);

                            // Keep references to cloned scripts for later restoration
                            if (hasScripts) {
                                jQuery.merge(scripts, getAll(node, "script"));
                            }
                        }

                        callback.call(this[i], node, i);
                    }

                    if (hasScripts) {
                        doc = scripts[scripts.length - 1].ownerDocument;

                        // Reenable scripts
                        jQuery.map(scripts, restoreScript);

                        // Evaluate executable scripts on first document insertion
                        for (i = 0; i < hasScripts; i++) {
                            node = scripts[i];
                            if (rscriptType.test(node.type || "") &&
                                !jQuery._data(node, "globalEval") && jQuery.contains(doc, node)) {

                                if (node.src) {
                                    // Optional AJAX dependency, but won't run scripts if not present
                                    if (jQuery._evalUrl) {
                                        jQuery._evalUrl(node.src);
                                    }
                                } else {
                                    jQuery.globalEval((node.text || node.textContent || node.innerHTML || "").replace(rcleanScript, ""));
                                }
                            }
                        }
                    }

                    // Fix #11809: Avoid leaking memory
                    fragment = first = null;
                }
            }

            return this;
        }
    });