如何使用 jquery 更改元素类型

IT技术 javascript jquery
2021-02-01 10:20:02

我有以下代码

<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>

我如何将b标签替换h1标签但保留所有其他属性和信息?

6个回答

这是您可以使用 jQuery 实现的一种方法:

var attrs = { };

$.each($("b")[0].attributes, function(idx, attr) {
    attrs[attr.nodeName] = attr.nodeValue;
});


$("b").replaceWith(function () {
    return $("<h1 />", attrs).append($(this).contents());
});

示例: http : //jsfiddle.net/yapHk/

更新,这是一个插件:

(function($) {
    $.fn.changeElementType = function(newType) {
        var attrs = {};

        $.each(this[0].attributes, function(idx, attr) {
            attrs[attr.nodeName] = attr.nodeValue;
        });

        this.replaceWith(function() {
            return $("<" + newType + "/>", attrs).append($(this).contents());
        });
    };
})(jQuery);

示例: http : //jsfiddle.net/mmNNJ/

@FelixKling:谢谢,没用,children没用contents
2021-03-12 10:20:02
@ciuncan:感谢您的反馈!它真的应该.each像下面的答案一样被包裹在一个块中。
2021-03-20 10:20:02
@AndrewWhitaker:如果我没记错的话,在您的插件中,第一个匹配元素的属性将应用于所有匹配元素。这不一定是我们想要的。当集合中没有匹配的元素时,也会引发错误。这是您插件的修改版本,它为每个匹配的元素保留自己的属性,并且不会在空集上触发错误:gist.github.com/2934516
2021-03-22 10:20:02
@安德鲁惠特克哇!!!你很厉害!所以只是为了确保我使用 b.class 或 b.xyzxterms (xyzxterms 是类的名称)
2021-04-02 10:20:02
这就像一个魅力!Except that when the selector fails to find any matching element, it throws an error message to console because this[0] is undefined accessing attributes breaks. 添加条件修复它: if (this.length != 0) {...
2021-04-08 10:20:02

不确定jQuery。使用纯 JavaScript,您可以执行以下操作:

var new_element = document.createElement('h1'),
    old_attributes = element.attributes,
    new_attributes = new_element.attributes;

// copy attributes
for(var i = 0, len = old_attributes.length; i < len; i++) {
    new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}

// copy child nodes
do {
    new_element.appendChild(element.firstChild);
} 
while(element.firstChild);

// replace element
element.parentNode.replaceChild(new_element, element);

演示

不确定这是如何跨浏览器兼容的。

一个变化可能是:

for(var i = 0, len = old_attributes.length; i < len; i++) {
    new_element.setAttribute(old_attributes[i].name, old_attributes[i].value);
}

有关更多信息,请参阅Node.attributes [MDN]

您的代码的性能比“纯 jQuery”(例如 Andrew 的代码)要好,但是内部标签有一点问题,请在此示例中使用您的代码参考示例查看斜体
2021-03-17 10:20:02
固定的。问题是在复制第一个孩子之后,它不再有下一个兄弟姐妹,所以while(child = child.nextSibling)失败了。谢谢!
2021-03-31 10:20:02
如果您更正,则可以定义“理想的 jquery 插件”,通过 jquery-plugin-template 调用您的函数。
2021-04-05 10:20:02

@jakov 和 @Andrew Whitaker

这是进一步的改进,因此它可以一次处理多个元素。

$.fn.changeElementType = function(newType) {
    var newElements = [];

    $(this).each(function() {
        var attrs = {};

        $.each(this.attributes, function(idx, attr) {
            attrs[attr.nodeName] = attr.nodeValue;
        });

        var newElement = $("<" + newType + "/>", attrs).append($(this).contents());

        $(this).replaceWith(newElement);

        newElements.push(newElement);
    });

    return $(newElements);
};

@Jazzbo 的回答返回了一个 jQuery 对象,其中包含一个不可链接的 jQuery 对象数组。我已经改变了它,使它返回一个更类似于 $.each 返回的对象:

    $.fn.changeElementType = function (newType) {
        var newElements,
            attrs,
            newElement;

        this.each(function () {
            attrs = {};

            $.each(this.attributes, function () {
                attrs[this.nodeName] = this.nodeValue;
            });

            newElement = $("<" + newType + "/>", attrs).append($(this).contents());

            $(this).replaceWith(newElement);

            if (!newElements) {
                newElements = newElement;
            } else {
                $.merge(newElements, newElement);
            }
        });

        return $(newElements);
    };

(还做了一些代码清理,以便通过 jslint。)

由于 jslint,我对 var 进行了分组:“(还做了一些代码清理,因此它通过了 jslint。)”。我认为这背后的想法是使代码更快(不必在每个each循环中重新声明变量)。
2021-03-24 10:20:02
这似乎是最好的选择。我唯一不明白的是为什么您将 attrs 的 var 声明从 this.each() 中移出。它留在那里工作正常:jsfiddle.net/9c0k82sr/1
2021-04-01 10:20:02

我能想到的唯一方法是手动复制所有内容:example jsfiddle

HTML

<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>

jQuery/Javascript

$(document).ready(function() {
    var me = $("b");
    var newMe = $("<h1>");
    for(var i=0; i<me[0].attributes.length; i++) {
        var myAttr = me[0].attributes[i].nodeName;
        var myAttrVal = me[0].attributes[i].nodeValue;
        newMe.attr(myAttr, myAttrVal);
    }
    newMe.html(me.html());
    me.replaceWith(newMe);
});