You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在两个DOM元素间交换指定子集属性?

解决元素特定属性交换失败的问题

你的代码问题出在保存了Attr对象的引用,而非属性的静态键值对。当你修改元素属性时,保存的Attr对象的value会同步更新,导致最终交换逻辑失效——相当于把修改后的属性又写回了原元素,等于没交换。

修正方案:保存属性的键值对副本

我们需要先把要交换的属性提取为独立的键值对对象(静态副本),再互相赋值给对方元素。这里可以结合你提到的解构赋值简化变量交换,或者直接完成属性赋值:

let elem1 = document.getElementById("item1");
let elem2 = document.getElementById("item2");
let before = document.getElementById("before");
let after = document.getElementById("after");

before.innerHTML = 'before: ' + showData(elem1,elem2);
swapAttributes(elem1,elem2);
after.innerHTML = 'after: ' + showData(elem1,elem2);

function showData(a,b) {
  let data1 = a.dataset;
  let data2 = b.dataset;
  return data1.keepRow + "," + data1.keepCol + " and " + data2.keepRow + "," + data2.keepCol;
}

function swapAttributes(el1, el2) {
  // 提取元素中需要交换的属性为键值对
  const extractKeepAttrs = (el) => {
    const attrs = {};
    [...el.attributes].forEach(attr => {
      if (attr.nodeName.startsWith("data-keep-")) {
        attrs[attr.name] = attr.value;
      }
    });
    return attrs;
  };

  const el1Attrs = extractKeepAttrs(el1);
  const el2Attrs = extractKeepAttrs(el2);

  // 先清空原元素的目标属性,再赋值对方的属性
  // 清空el1的data-keep-*属性
  Object.keys(el1Attrs).forEach(key => el1.removeAttribute(key));
  // 给el1设置el2的属性
  Object.entries(el2Attrs).forEach(([key, value]) => el1.setAttribute(key, value));

  // 同理处理el2
  Object.keys(el2Attrs).forEach(key => el2.removeAttribute(key));
  Object.entries(el1Attrs).forEach(([key, value]) => el2.setAttribute(key, value));
}
<div id="item1" data-keep-row=1 data-keep-col=1>item1</div>
<div id="item2" data-keep-row=2 data-keep-col=2>item2</div>
<p id="before"></p>
<p id="after"></p>

解构赋值的应用

如果你想用解构赋值简化变量交换逻辑,可以在提取属性后先交换两个变量,再分别赋值给元素:

// 在swapAttributes函数中,提取属性后:
[el1Attrs, el2Attrs] = [el2Attrs, el1Attrs];

// 然后将交换后的属性赋值给对应元素
Object.keys(el1Attrs).forEach(key => el1.removeAttribute(key));
Object.entries(el1Attrs).forEach(([key, value]) => el1.setAttribute(key, value));

Object.keys(el2Attrs).forEach(key => el2.removeAttribute(key));
Object.entries(el2Attrs).forEach(([key, value]) => el2.setAttribute(key, value));

这里的解构赋值只是交换了两个存储属性的对象变量,核心还是用静态的键值对副本避免引用同步问题。

内容的提问来源于stack exchange,提问作者quilkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:44:59