【问题标题】:How to copy all the attributes of one element and apply them to another?如何复制一个元素的所有属性并将它们应用于另一个元素?
【发布时间】:2011-07-19 20:01:40
【问题描述】:

如何将一个元素的属性复制到另一个元素?

HTML

<select id="foo" class="bar baz" style="display:block" width="100" data-foo="bar">...</select>

<div>No attributes yet</div>

JavaScript

var $div = $('div');
var $select = $('select');

//now copy the attributes from $select to $div

【问题讨论】:

  • 您确定要复制id
  • 如果要复制id 属性,您将有一个重复的id
  • 也许您可以解释一下为什么需要这样做?可能有更好的解决方案。
  • 别担心,我不会复制ID属性或删除重复的ID属性。
  • 因为如果我手动复制每个属性,我不想忘记一个属性。另外,我不知道该怎么做,所以我想问一下,以便我将来可以学习如何做。

标签: javascript jquery


【解决方案1】:

您可以使用原生的Node#attributes 属性:http://jsfiddle.net/SDWHN/16/

var $select = $("select");
var $div = $("div");

var attributes = $select.prop("attributes");

// loop through <select> attributes and apply them on <div>
$.each(attributes, function() {
    $div.attr(this.name, this.value);
});

alert($div.data("foo"));

【讨论】:

  • 注意:属性数组远不兼容。是的,它是核心,但早期版本的 IE 会随心所欲地处理“核心”属性。我使用“hackish”,但作为悖论,从forum.jquery.com/topic/… 采取更兼容的方式 - 使节点成为字符串表示,用正则表达式更改它的标签并转换回节点。然后我可以重新附加数据和事件。 IE 版本在复制某些属性时抛出错误(例如“实现”属性 - 你知道它附加到所有标签吗?)
  • 当您的变量包含对 jQuery 对象的引用时,请在变量前面加上“$”。我在我现在的公司开始了这种趋势......它使快速阅读代码变得更加容易!
  • 想问一个与此相关的附带问题。我试过$something.prop('attributes'),它给出了一个带有属性的数组。其中一个是crossorigin 用于图像。我尝试了未定义的$item.prop('crossorigin'),但如果我尝试$item.prop('src'),它会给出结果。然后我尝试了$item.attr('crossorigin'),它给出了价值。 .attr().prop() 有什么区别?为什么上述情况有些不同?提前致谢。
  • @simongcc .prop 从底层原生 Node 对象中获取一个属性,表示元素的 DOM。 .attr 获取以编程方式或通过标记定义的 HTML 属性的值。
【解决方案2】:

ES6 语法单行:

function cloneAttributes(target, source) {
  [...source.attributes].forEach( attr => { target.setAttribute(attr.nodeName ,attr.nodeValue) })
}

正如第一条评论中所述 - 您可能不想复制源 id 属性...所以这个会将其保存为“data-id”属性以防您需要参考。

function cloneAttributes(target, source) {
  [...source.attributes].forEach( attr => { target.setAttribute(attr.nodeName === "id" ? 'data-id' : attr.nodeName ,attr.nodeValue) })
}

【讨论】:

  • 迄今为止的最佳答案。现在是 2020 年。
【解决方案3】:

很简单

function cloneAttributes(element, sourceNode) {
  let attr;
  let attributes = Array.prototype.slice.call(sourceNode.attributes);
  while(attr = attributes.pop()) {
    element.setAttribute(attr.nodeName, attr.nodeValue);
  }
}

【讨论】:

  • 另请注意,此方法不会复制任何不必要的原始类型。它只克隆每个属性。
  • 您使用Array#slicewhile 而不仅仅是Array#forEach 有什么原因吗?
  • 可能是为了兼容死浏览器。
【解决方案4】:

A working solution on jsfiddle

编辑

更新 jsfiddler

Javascript

$(function(){
    var destination = $('#adiv').eq(0);
    var source = $('#bdiv')[0];

    for (i = 0; i < source.attributes.length; i++)
    {
        var a = source.attributes[i];
        destination.attr(a.name, a.value);
    }
});

HTML

<div id="adiv" class="aclass">A class</div>
<div id="bdiv" class="bclass">B class</div>

这是将#bdiv 属性复制到#adiv

【讨论】:

  • 你应该至少在这里发布你的代码的重要部分,如果没有其他原因,如果 jsfiddle 消失了,你的答案仍然存在。
  • @kingjiv,感谢您的建议。
  • 这似乎在 IE (8) 中存在问题,它发现太多属性 (100+) 并且 jQuery 在尝试设置属性时抛出未找到成员异常。
【解决方案5】:

我们还可以尝试扩展 jQuery 原型 ($.fn) 对象,以提供可以链接到 jQuery() 函数的新方法。

这里是@pimvdb 解决方案的一个扩展,提供了一个复制所有属性的功能

用法是这样的:

 $(destinationElement).copyAllAttributes(sourceElement);

扩展函数可以这样定义:

(function ($) {

    // Define the function here
    $.fn.copyAllAttributes = function(sourceElement) {

        // 'that' contains a pointer to the destination element
        var that = this;

        // Place holder for all attributes
        var allAttributes = ($(sourceElement) && $(sourceElement).length > 0) ?
            $(sourceElement).prop("attributes") : null;

        // Iterate through attributes and add    
        if (allAttributes && $(that) && $(that).length == 1) {
            $.each(allAttributes, function() {
                // Ensure that class names are not copied but rather added
                if (this.name == "class") {
                    $(that).addClass(this.value);
                } else {
                    that.attr(this.name, this.value);
                }

            });
        }

        return that;
    }; 

})(jQuery);

http://jsfiddle.net/roeburg/Z8x8x/ 上提供了一个示例

希望这会有所帮助。

【讨论】:

  • 您的代码有不必要的重复 jQuery 包装器/初始化。查看我的更改:jsfiddle.net/5eLdcya6
【解决方案6】:

非 jquery 解决方案:

function copy(element){
    var clone = document.createElement(element.nodeName);
    for(key in element){
        clone.setAttribute(key,element[key]);
    }
    return clone;
}

它复制了您可能不需要的方法和其他东西,但希望您不介意。这段代码小而简单。

【讨论】:

    【解决方案7】:

    你可以试试这个:

    function copyAttributes(from, to)
    {
      $($(from)[0].attributes).
        each(function(){$(to).attr(this.nodeName, this.nodeValue);});
    
      return $(to);
    };
    

    return 语句让您可以编写如下内容:

    copyAttributes(some_element, $('<div></div>')).append(...) ...
    

    希望这会有所帮助。

    【讨论】:

      【解决方案8】:

      我也面临同样的问题,经过投入大量时间和精力,我正在创建这个clone textarea into editable div with same attribute

      select.getAttributeNames().forEach(attrName => {
        $(div).attr(attrName, inputData.getAttribute(attrName));
      });
      

      【讨论】:

        【解决方案9】:

        一个非常直接的解决方案是这样的:

        const _$ = domQuery => document.querySelector(domQuery)
        let div1 = _$('#div-1')
        let div2 = _$('#div-2')
        
        for(attr of div1.attributes) {
          div2.setAttribute(attr.name, attr.value);
        }
        .my-div {
        height: 100px;
        width: 100px;
        }
        <h1>div-1</h1>
        <div atribute-test="test" class="my-div" style="background: red" id="div-1"></div>
        <h1>div-2</h1>
        <div id="div-2"></div>

        【讨论】:

          【解决方案10】:

          从 Firefox 22 开始,不再支持 Node.attributes(其他浏览器未实现并从规范中删除)。它仅在 Element (Element.attributes) 上受支持。

          【讨论】:

          • 这对OP来说根本不重要,他不谈文本或其他节点。
          【解决方案11】:

          Javascript 解决方案

          将旧元素的属性复制到新元素中

          const $oldElem = document.querySelector('.old')
          const $newElem = document.createElement('div')
          
          Array.from($oldElem.attributes).map(a => {
            $newElem.setAttribute(a.name, a.value)
          })
          

          如果需要,用新元素替换旧元素

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

          【讨论】:

            【解决方案12】:
            $("div").addClass($('#foo').attr('class'));
            

            【讨论】:

            • 我的错,我以为你想复制 css。
            • 虽然这是一个错误,但这正是我在谷歌上搜索的目的。那谢谢啦! ;)
            猜你喜欢
            • 1970-01-01
            • 2011-05-28
            • 2022-12-18
            • 2012-02-13
            • 2020-05-08
            • 2010-11-12
            • 1970-01-01
            • 1970-01-01
            • 2023-04-04
            相关资源
            最近更新 更多