修改元素outerHTML后,如何让对象引用新DOM元素而非旧元素?
解决修改outerHTML后变量引用旧DOM元素的问题
你遇到的问题确实是outerHTML的典型陷阱——当你用它替换DOM元素时,虽然页面上的元素已经被新内容替换,但原来的bar变量依然指向那个被从DOM中移除的旧<p>元素。所以你传给Foo的其实是一个“离线”的元素,后续调用doFoo修改它的内容自然不会反映到页面上的新<h1>元素。正如MDN明确说明的:
While the element will be replaced in the document, the variable whose outerHTML property was set will still hold a reference to the original element
要让Foo对象获取到DOM中的新元素,同时不需要重新查询DOM,有两种简洁的方案:
方案1:手动创建新元素并替换
这种方法直接创建新元素,替换旧元素后直接拿到新元素的引用,逻辑清晰直观:
const bars = document.getElementsByClassName('bar'); for (let i = bars.length - 1; i >= 0; i -= 1) { const bar = bars[i]; // 创建新的h1元素并赋值属性和内容 const newBar = document.createElement('h1'); newBar.className = 'bar'; newBar.innerHTML = bar.innerHTML; // 替换旧元素,同时保留新元素的引用 bar.parentNode.replaceChild(newBar, bar); // 把新元素传给Foo实例 const foo = new Foo(newBar); foo.doFoo(); } function Foo (bar) { this.bar = bar; this.doFoo = function() { this.bar.innerHTML = `Foo${this.bar.innerHTML}`; console.log('doFoo:', this.bar.innerHTML); } }
方案2:利用insertAdjacentHTML获取新元素
如果你更倾向于用HTML字符串来定义新元素,可以用insertAdjacentHTML插入新元素,然后通过旧元素的位置获取新元素,再移除旧元素:
const bars = document.getElementsByClassName('bar'); for (let i = bars.length - 1; i >= 0; i -= 1) { const bar = bars[i]; // 在旧元素的前方插入新的h1元素 bar.insertAdjacentHTML('beforebegin', `<h1 class="bar">${bar.innerHTML}</h1>`); // 获取刚插入的新元素(旧元素的前一个兄弟节点) const newBar = bar.previousElementSibling; // 移除已经没用的旧元素 bar.remove(); // 把新元素传给Foo实例 const foo = new Foo(newBar); foo.doFoo(); } function Foo (bar) { this.bar = bar; this.doFoo = function() { this.bar.innerHTML = `Foo${this.bar.innerHTML}`; console.log('doFoo:', this.bar.innerHTML); } }
这两种方案都不需要用getElementsByClassName或querySelector重新查询DOM,直接在替换过程中拿到了新元素的引用,完美解决你的问题。
内容的提问来源于stack exchange,提问作者Beppe
相关产品推荐
相关产品推荐

