【问题标题】:Use jQuery to change an HTML tag?使用 jQuery 更改 HTML 标签?
【发布时间】:2009-05-28 01:28:18
【问题描述】:

这可能吗?

示例:

$('a.change').click(function(){
//code to change p tag to h5 tag
});


<p>Hello!</p>
<a id="change">change</a>

因此,单击更改锚点应该会导致 &lt;p&gt;Hello!&lt;/p&gt; 部分更改为(例如)一个 h5 标记,因此单击后您最终会得到 &lt;h5&gt;Hello!&lt;/h5&gt;。我知道你可以删除 p 标签并用 h5 替换它,但是无论如何要真正修改 HTML 标签?

【问题讨论】:

    标签: jquery


    【解决方案1】:

    我相信,一旦创建了 dom 元素,标签就是不可变的。你必须这样做:

    $(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));
    

    【讨论】:

    • 请在下面查看我的评论...更改文档结构以应用样式不是最好的方法。
    • 这不会破坏您替换的元素上可能存在的任何属性吗?由于删除了样式属性、数据属性等,可能会导致一些意外行为...
    • "&lt;" + el.outerHTML.replace(/(^&lt;\w+|\w+&gt;$)/g, "H5") + "&gt;"; 或可插入的jQuery函数:link
    【解决方案2】:

    这是一个扩展,可以在尽可能多的元素上以尽可能多的方式完成所有工作......

    示例用法:

    保留现有的类和属性:

    $('div#change').replaceTag('&lt;span&gt;', true);

    丢弃现有的类和属性:

    $('div#change').replaceTag('&lt;span class=newclass&gt;', false);

    甚至

    用 span 替换所有 div,复制类和属性,添加额外的类名

    $('div').replaceTag($('&lt;span&gt;').addClass('wasDiv'), true);

    插件源:

    $.extend({
        replaceTag: function (currentElem, newTagObj, keepProps) {
            var $currentElem = $(currentElem);
            var i, $newTag = $(newTagObj).clone();
            if (keepProps) {//{{{
                newTag = $newTag[0];
                newTag.className = currentElem.className;
                $.extend(newTag.classList, currentElem.classList);
                $.extend(newTag.attributes, currentElem.attributes);
            }//}}}
            $currentElem.wrapAll($newTag);
            $currentElem.contents().unwrap();
            // return node; (Error spotted by Frank van Luijn)
            return this; // Suggested by ColeLawrence
        }
    });
    
    $.fn.extend({
        replaceTag: function (newTagObj, keepProps) {
            // "return" suggested by ColeLawrence
            return this.each(function() {
                jQuery.replaceTag(this, newTagObj, keepProps);
            });
        }
    });
    

    【讨论】:

    • 是的。并且为了记录,实际上有很多非常正当的理由你可能想要更改标签。例如如果您在 SPAN 中有 DIV 标签,这是非标准的。在使用princexml的严格标准进行pdb发布时,我已经从这个功能中得到了很多用处。
    • 看起来很不错,但不幸的是它丢失了被替换元素的所有事件。也许这也可以处理——太棒了!
    • @FrankvanLuijn @orwellophile return node; 实际上应该是 return this;,如插件的“旧版本”所示。这对于将事件链接在一起至关重要,例如$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
    • 我不明白,为什么需要 2 个函数?你两个都需要吗?对不起,我迷路了
    • @adaliabooks 应该,我现在在我的 GreaseMonkey SO 上下文格式化程序中使用它的稍微修改过的版本 -- gist.github.com/sfinktah/f7f8f290e49735742cb20b140dbe0e70 (Google Chrome)。是的——我刚刚对照这个页面检查了这篇文章中发布的代码,它可以工作。 $('div[itemprop="upvoteCount"]').replaceTag($('&lt;span&gt;').addClass('wasDiv'), true);
    【解决方案3】:

    您应该更改标签的样式(或者更确切地说,更改具有特定 id 的标签)而不是更改标签的类型。更改文档的元素以应用样式更改并不是一个好习惯。试试这个:

    $('a.change').click(function() {
        $('p#changed').css("font-weight", "bold");
    });
    
    <p id="changed">Hello!</p>
    <a id="change">change</a>
    

    【讨论】:

    • 即使在这种情况下,您也不应该修改文档结构。如果您需要显示输入以响应单击编辑按钮,则将输入放入并粘贴 display:none 或 visibility:hidden 。隐藏
      并显示 以响应按钮单击。如果您不断地修改文档结构……您只是要求在路上遇到一大堆样式和布局问题。
    • 当然。您的 javascript 是嵌入或链接的,因此如果您关心的是安全性,那么您的安全性方法有些缺陷。您应该根据用户的角色呈现文档的内容...为角色混合内容并不是解决问题的安全方法。如果有人以管理员身份登录到您的系统,请为管理员呈现内容。如果他们作为阅读器登录到您的系统,则为阅读器呈现内容。这完全消除了不应访问的内容。呈现内容后,使用 CSS 设置文档样式并显示/隐藏内容。
    • 我同意你的观点,并将你的建议纳入项目。我将使用 toggle() 显示仅在管理员登录时才呈现的管理元素。虽然与原始问题无关(直接),但这可能是比我最初的方向更好的解决方案。干杯!
    • 哇!袋装另一个糟糕的安全性!一场胜利,一场比赛! (在此处插入啤酒图标)
    • 依靠客户端javascript来保证安全性实际上比没有安全性要更糟糕。为什么?因为你认为你有安全感,而事实上你没有。
    【解决方案4】:

    我注意到第一个答案并不是我所需要的,所以我做了一些修改并想把它贴回这里。

    改进了replaceTag(&lt;tagName&gt;)

    replaceTag(&lt;tagName&gt;, [withDataAndEvents], [withDataAndEvents])

    参数:

    • 标签名称:字符串
      • 标签名称,例如“div”、“span”等。
    • withDataAndEvents:布尔值
      • “一个布尔值,指示是否应将事件处理程序与元素一起复制。从 jQuery 1.4 开始,元素数据也将被复制。” info
    • deepWithDataAndEvents:布尔值
      • 一个布尔值,指示是否应复制克隆元素的所有子元素的事件处理程序和数据。默认情况下,它的值与第一个参数的值匹配(默认为 false)。”info

    返回:

    一个新创建的 jQuery 元素

    好的,我知道现在这里有一些答案,但我自己又写了一遍。

    这里我们可以像使用克隆一样替换标签。 我们遵循与.clone() 相同的语法,使用withDataAndEventsdeepWithDataAndEvents 复制 节点的数据和事件(如果使用)。

    示例:

    $tableRow.find("td").each(function() {
      $(this).clone().replaceTag("li").appendTo("ul#table-row-as-list");
    });
    

    来源:

    $.extend({
        replaceTag: function (element, tagName, withDataAndEvents, deepWithDataAndEvents) {
            var newTag = $("<" + tagName + ">")[0];
            // From [Stackoverflow: Copy all Attributes](http://stackoverflow.com/a/6753486/2096729)
            $.each(element.attributes, function() {
                newTag.setAttribute(this.name, this.value);
            });
            $(element).children().clone(withDataAndEvents, deepWithDataAndEvents).appendTo(newTag);
            return newTag;
        }
    })
    $.fn.extend({
        replaceTag: function (tagName, withDataAndEvents, deepWithDataAndEvents) {
            // Use map to reconstruct the selector with newly created elements
            return this.map(function() {
                return jQuery.replaceTag(this, tagName, withDataAndEvents, deepWithDataAndEvents);
            })
        }
    })
    

    请注意,此不会替换所选元素,它会返回新创建的元素。

    【讨论】:

    • 请注意.children() 不会包含任何纯文本节点。你可能想试试.contents()IIRC。
    【解决方案5】:

    想法是包装元素并打开内容:

    function renameElement($element,newElement){
    
        $element.wrap("<"+newElement+">");
        $newElement = $element.parent();
    
        //Copying Attributes
        $.each($element.prop('attributes'), function() {
            $newElement.attr(this.name,this.value);
        });
    
        $element.contents().unwrap();       
    
        return $newElement;
    }
    

    示例用法:

    renameElement($('p'),'h5');
    

    Demo

    【讨论】:

      【解决方案6】:

      我想出了一种方法,您可以使用 jQuery 对象的字符串表示,并使用正则表达式和基本 JavaScript 替换标记名称。您不会丢失任何内容,也不必遍历每个属性/属性。

      /*
       * replaceTag
       * @return {$object} a new object with replaced opening and closing tag
       */
      function replaceTag($element, newTagName) {
      
        // Identify opening and closing tag
        var oldTagName = $element[0].nodeName,
          elementString = $element[0].outerHTML,
          openingRegex = new RegExp("^(<" + oldTagName + " )", "i"),
          openingTag = elementString.match(openingRegex),
          closingRegex = new RegExp("(<\/" + oldTagName + ">)$", "i"),
          closingTag = elementString.match(closingRegex);
      
        if (openingTag && closingTag && newTagName) {
          // Remove opening tag
          elementString = elementString.slice(openingTag[0].length);
          // Remove closing tag
          elementString = elementString.slice(0, -(closingTag[0].length));
          // Add new tags
          elementString = "<" + newTagName + " " + elementString + "</" + newTagName + ">";
        }
      
        return $(elementString);
      }
      

      最后,您可以按如下方式替换现有对象/节点:

      var $newElement = replaceTag($rankingSubmit, 'a');
      $('#not-an-a-element').replaceWith($newElement);
      

      【讨论】:

        【解决方案7】:

        这是我的解决方案。它允许在标签之间切换。

        <!DOCTYPE html>
        <html>
        <head>
        	<title></title>
        
        <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
        <script type="text/javascript">
        
        function wrapClass(klass){
        	return 'to-' + klass;
        }
        
        function replaceTag(fromTag, toTag){
        	
        	/** Create selector for all elements you want to change.
        	  * These should be in form: <fromTag class="to-toTag"></fromTag>
        	  */
        	var currentSelector = fromTag + '.' + wrapClass(toTag);
        
        	/** Select all elements */
        	var $selected = $(currentSelector);
        
        	/** If you found something then do the magic. */
        	if($selected.size() > 0){
        
        		/** Replace all selected elements */
        		$selected.each(function(){
        
        			/** jQuery current element. */
        			var $this = $(this);
        
        			/** Remove class "to-toTag". It is no longer needed. */
        			$this.removeClass(wrapClass(toTag));
        
        			/** Create elements that will be places instead of current one. */
        			var $newElem = $('<' + toTag + '>');
        
        			/** Copy all attributes from old element to new one. */
        			var attributes = $this.prop("attributes");
        			$.each(attributes, function(){
        				$newElem.attr(this.name, this.value);
        			});
        
        			/** Add class "to-fromTag" so you can remember it. */
        			$newElem.addClass(wrapClass(fromTag));
        
        			/** Place content of current element to new element. */
        			$newElem.html($this.html());
        
        			/** Replace old with new. */
        			$this.replaceWith($newElem);
        		});
        
        		/** It is possible that current element has desired elements inside.
        		  * If so you need to look again for them.
        		  */
        		replaceTag(fromTag, toTag);
        	}
        }
        
        
        </script>
        
        <style type="text/css">
        	
        	section {
        		background-color: yellow;
        	}
        
        	div {
        		background-color: red;
        	}
        
        	.big {
        		font-size: 40px;
        	}
        
        </style>
        </head>
        <body>
        
        <button onclick="replaceTag('div', 'section');">Section -> Div</button>
        <button onclick="replaceTag('section', 'div');">Div -> Section</button>
        
        <div class="to-section">
        	<p>Matrix has you!</p>
        	<div class="to-section big">
        		<p>Matrix has you inside!</p>
        	</div>
        </div>
        
        <div class="to-section big">
        	<p>Matrix has me too!</p>
        </div>
        
        </body>
        </html>

        【讨论】:

          【解决方案8】:

          这是使用 jQuery 在 DOM 中更改 HTML 标签的快速方法。我发现这个replaceWith() 函数非常有用。

             var text= $('p').text();
             $('#change').on('click', function() {
               target.replaceWith( "<h5>"+text+"</h5>" );
             });
          

          【讨论】:

            【解决方案9】:

            您可以通过data-* 属性如data-replace="replaceTarget,replaceBy" 来实现,因此在jQuery 的帮助下通过.split() 方法获取replaceTargetreplaceBy 值,然后使用.replaceWith() 方法。
            这种data-* 属性技术可以轻松管理任何标签替换,而无需更改以下内容(所有标签替换的通用代码)。

            希望下面的sn-p能帮到你。

            $(document).on('click', '[data-replace]', function(){
              var replaceTarget = $(this).attr('data-replace').split(',')[0];
              var replaceBy = $(this).attr('data-replace').split(',')[1];
              $(replaceTarget).replaceWith($(replaceBy).html($(replaceTarget).html()));
            });
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            
            <p id="abc">Hello World #1</p>
            <a href="#" data-replace="#abc,<h1/>">P change with H1 tag</a>
            <hr>
            <h2 id="xyz">Hello World #2</h2>
            <a href="#" data-replace="#xyz,<p/>">H1 change with P tag</a>
            <hr>
            <b id="bold">Hello World #2</b><br>
            <a href="#" data-replace="#bold,<i/>">B change with I tag</a>
            <hr>
            <i id="italic">Hello World #2</i><br>
            <a href="#" data-replace="#italic,<b/>">I change with B tag</a>

            【讨论】:

              【解决方案10】:

              以下函数可以解决问题并保留所有属性。例如,您可以像这样使用它:changeTag("div", "p")

              function changeTag(originTag, destTag) {
                while($(originTag).length) {
                  $(originTag).replaceWith (function () {
                    var attributes = $(this).prop("attributes");
                    var $newEl = $(`<${destTag}>`)
                    $.each(attributes, function() {
                      $newEl.attr(this.name, this.value);
                    });  
                    return $newEl.html($(this).html())
                  })
                }
              }
              

              为确保它有效,请检查以下示例

              function changeTag(originTag, destTag) {
                while($(originTag).length) {
                  $(originTag).replaceWith (function () {
                    var attributes = $(this).prop("attributes");
                    var $newEl = $(`<${destTag}>`)
                    $.each(attributes, function() {
                      $newEl.attr(this.name, this.value);
                    });  
                    return $newEl.html($(this).html())
                  })
                }
              }
              
              changeTag("div", "p")
              
              console.log($("body").html())
              <body>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
              
              <div class="A" style="font-size:1em">
                <div class="B" style="font-size:1.1em">A</div>
              </div>
              <div class="C" style="font-size:1.2em">
                B
              </div>
              </body>

              【讨论】:

                【解决方案11】:

                是否有特定原因需要更改标签?如果你只是想让文本变大,改变 p 标签的 CSS 类会是一个更好的方法。

                类似这样的:

                $('#change').click(function(){
                  $('p').addClass('emphasis');
                });
                

                【讨论】:

                • 我要求更改元素/标签的原因是因为我试图在“编辑" 按钮被点击页面上的其他地方。
                猜你喜欢
                • 1970-01-01
                • 2012-02-11
                • 2010-12-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-11-14
                • 2017-04-09
                • 1970-01-01
                相关资源
                最近更新 更多