cách thay đổi kiểu phần tử bằng jquery


Câu trả lời:


137

Đây là một cách bạn có thể làm với jQuery:

var attrs = { };

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


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

Ví dụ: http://jsfiddle.net/yapHk/

Cập nhật , đây là một plugin:

(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);

Ví dụ: http://jsfiddle.net/mmNNJ/


2
@FelixKling: Cảm ơn, childrenkhông hoạt động nhưng contentsđã làm.
Andrew Whitaker

1
@Andrew Whitaker WOW !!! bạn tốt! Vì vậy, chỉ để chắc chắn tôi sử dụng b.class hoặc b.xyzxterms (xyzxterms là tên của lớp)
bammab

5
@AndrewWhitaker: Nếu tôi không nhầm, trong plugin của bạn, các thuộc tính của phần tử phù hợp đầu tiên sẽ được áp dụng cho tất cả các phần tử phù hợp. Nó không nhất thiết phải là những gì chúng ta muốn. Ngoài ra, một lỗi cũng phát sinh khi không có phần tử phù hợp trong tập hợp. Đây là phiên bản sửa đổi của plugin của bạn giữ các thuộc tính riêng cho từng phần tử phù hợp và không gây ra lỗi trên tập hợp trống: gist.github.com/2934516
Etienne

2
Công việc này như một cái duyên vậy! Ngoại trừ trường hợp bộ chọn không tìm thấy bất kỳ phần tử phù hợp nào, nó sẽ ném một thông báo lỗi tới bảng điều khiển vì [0] này là các thuộc tính truy cập không xác định. Thêm một bản vá điều kiện nó: if (! This.length = 0) {...
ciuncan

1
@ciuncan: Cảm ơn bạn đã phản hồi! Nó thực sự nên được bao bọc trong một .eachkhối như câu trả lời bên dưới cũng hiển thị.
Andrew Whitaker

14

Không chắc chắn về jQuery. Với JavaScript đơn giản, bạn có thể làm:

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);

BẢN GIỚI THIỆU

Tuy nhiên, không chắc chắn điều này tương thích với nhiều trình duyệt như thế nào.

Một biến thể có thể là:

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

Để biết thêm thông tin, hãy xem Node.attributes [MDN] .


Hiệu suất của mã của bạn tốt hơn "jQuery thuần túy" (ví dụ: mã của Andrew), nhưng có một chút vấn đề với các thẻ bên trong, hãy xem chữ nghiêng ở ví dụ này với mã của bạnví dụ tham chiếu .
Peter Krauss,

Nếu bạn sửa, một "plugin jquery lý tưởng" có thể được xác định, gọi hàm của bạn bằng jquery-plugin-template.
Peter Krauss,

Đã sửa. Vấn đề là sau khi sao chép con đầu tiên, nó không có anh chị em tiếp theo nữa, vì vậy while(child = child.nextSibling)không thành công. Cảm ơn!
Felix Kling,

9

@jakov và @Andrew Whitaker

Đây là một cải tiến hơn nữa để nó có thể xử lý nhiều phần tử cùng một lúc.

$.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);
};

3

Câu trả lời của @ Jazzbo trả về một đối tượng jQuery chứa một mảng các đối tượng jQuery, không thể ghép được. Tôi đã thay đổi nó để nó trả về một đối tượng giống với những gì $ .each sẽ trả về:

    $.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);
    };

(Cũng đã thực hiện một số dọn dẹp mã để nó vượt qua jslint.)


Đây có vẻ là lựa chọn đẹp nhất. Điều duy nhất tôi không hiểu là tại sao bạn lại chuyển khai báo var cho attrs ra khỏi this.each (). Nó hoạt động tốt với nó để lại ở đó: jsfiddle.net/9c0k82sr/1
Jacob C. nói Khôi phục Monica

Tôi đã nhóm các vars vì jslint: "(Cũng đã thực hiện một số dọn dẹp mã để nó vượt qua jslint.)". Ý tưởng đằng sau đó là làm cho mã nhanh hơn, tôi nghĩ (không cần phải khai báo lại các vars trong mỗi eachvòng lặp).
fiskhandlarn

2

Cách duy nhất tôi có thể nghĩ đến là sao chép mọi thứ theo cách thủ công: ví dụ 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);
});

2

@Andrew Whitaker: Tôi đề xuất thay đổi này:

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

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

    var newelement = $("<" + newType + "/>", attrs).append($(this).contents());
    this.replaceWith(newelement);
    return newelement;
};

Sau đó, bạn có thể làm những việc như: $('<div>blah</div>').changeElementType('pre').addClass('myclass');


2

Tôi thích ý tưởng của @AndrewWhitaker và những người khác, sử dụng một plugin jQuery - để thêm changeElementType()phương thức. Nhưng một plugin giống như một hộp đen, không có phần mềm nào về mã, nếu nó hoạt động tốt ... Vì vậy, hiệu suất là bắt buộc, và quan trọng nhất là mã.

"JavaScript thuần túy" có hiệu suất tốt hơn jQuery: Tôi nghĩ rằng mã của @ FelixKling có hiệu suất tốt hơn mã của @ AndrewWhitaker và các mã khác.


Đây là mã "Javavascript thuần" (và "DOM thuần"), được đóng gói trong một plugin jQuery :

 (function($) {  // @FelixKling's code
    $.fn.changeElementType = function(newType) {
      for (var k=0;k<this.length; k++) {
       var e = this[k];
       var new_element = document.createElement(newType),
        old_attributes = e.attributes,
        new_attributes = new_element.attributes,
        child = e.firstChild;
       for(var i = 0, len = old_attributes.length; i < len; i++) {
        new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
       }
       do {
        new_element.appendChild(e.firstChild);
       }
       while(e.firstChild);
       e.parentNode.replaceChild(new_element, e);
      }
      return this; // for chain... $(this)?  not working with multiple 
    }
 })(jQuery);

2

Đây là một phương pháp tôi sử dụng để thay thế các thẻ html trong jquery:

// Iterate over each element and replace the tag while maintaining attributes
$('b.xyzxterms').each(function() {

  // Create a new element and assign it attributes from the current element
  var NewElement = $("<h1 />");
  $.each(this.attributes, function(i, attrib){
    $(NewElement).attr(attrib.name, attrib.value);
  });

  // Replace the current element with the new one and carry over the contents
  $(this).replaceWith(function () {
    return $(NewElement).append($(this).contents());
  });

});

2

Với jQuery mà không cần lặp qua các thuộc tính:

Các replaceElemphương pháp dưới đây chấp nhận old Tag, new Tagcontextvà thực hiện việc thay thế thành công:


replaceElem('h2', 'h1', '#test');

function replaceElem(oldElem, newElem, ctx) {
  oldElems = $(oldElem, ctx);
  //
  $.each(oldElems, function(idx, el) {
    var outerHTML, newOuterHTML, regexOpeningTag, regexClosingTag, tagName;
    // create RegExp dynamically for opening and closing tags
    tagName = $(el).get(0).tagName;
    regexOpeningTag = new RegExp('^<' + tagName, 'i'); 
    regexClosingTag = new RegExp(tagName + '>$', 'i');
    // fetch the outer elem with vanilla JS,
    outerHTML = el.outerHTML;
    // start replacing opening tag
    newOuterHTML = outerHTML.replace(regexOpeningTag, '<' + newElem);
    // continue replacing closing tag
    newOuterHTML = newOuterHTML.replace(regexClosingTag, newElem + '>');
    // replace the old elem with the new elem-string
    $(el).replaceWith(newOuterHTML);
  });

}
h1 {
  color: white;
  background-color: blue;
  position: relative;
}

h1:before {
  content: 'this is h1';
  position: absolute;
  top: 0;
  left: 50%;
  font-size: 5px;
  background-color: black;
  color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div id="test">
  <h2>Foo</h2>
  <h2>Bar</h2>
</div>

Chúc may mắn...


1
Tôi thích câu trả lời của bạn! Tại sao? Bởi vì TẤT CẢ các câu trả lời khác sẽ thất bại khi cố gắng thực hiện một điều gì đó đơn giản như chuyển đổi một liên kết thành một nhãn. Điều đó nói rằng, vui lòng xem xét các bản sửa lỗi / sửa đổi sau cho câu trả lời của bạn: A). Mã của bạn sẽ không hoạt động với bộ chọn. B) Mã của bạn cần thực hiện regex không phân biệt chữ hoa chữ thường. Điều đó nói rằng, đây là các bản sửa lỗi được đề xuất của tôi: regexOpeningTag = new RegExp ('^ <' + $ (el) .get (0) .tagName, 'i'); regexClosingTag = new RegExp ($ (el) .get (0) .tagName + '> $', 'i');
zax 09/07/18

Việc thay thế HTML thuần túy như thế này cũng sẽ khiến bạn mất bất kỳ trình lắng nghe sự kiện nào được gắn vào các đối tượng.
José Yánez

1

Giải pháp Javascript

Sao chép các thuộc tính của phần tử cũ sang phần tử mới

const $oldElem = document.querySelector('.old')
const $newElem = document.createElement('div')

Array.from($oldElem.attributes).map(a => {
  $newElem.setAttribute(a.name, a.value)
})

Thay thế phần tử cũ bằng phần tử mới

$oldElem.parentNode.replaceChild($newElem, $oldElem)

maptạo một mảng mới chưa sử dụng, nó có thể được thay thế bằng forEach.
Orkhan Alikhanov

1

Đây là phiên bản của tôi. Về cơ bản đây là phiên bản của @ fiskhandlarn, nhưng thay vì xây dựng một đối tượng jQuery mới, nó chỉ ghi đè các phần tử cũ bằng các phần tử mới được tạo, vì vậy không cần hợp nhất.
Demo: http://jsfiddle.net/0qa7wL1b/

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

  this.each( function( index ){

    var atts = {};
    $.each( this.attributes, function(){
      atts[ this.name ] = this.value;
    });

    var $old = $(this);
    var $new = $('<'+ newType +'/>', atts ).append( $old.contents() );
    $old.replaceWith( $new );

    $this[ index ] = $new[0];
  });

  return this;
};
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.