开发者问题收集

JS:第一次调用后的函数导致空错误

2020-12-10
63

我只是随便玩了一下,然后转到 CNN 文章并在控制台中运行了此代码。这个想法是能够单击 p 元素,它会将 DOM 节点替换为其中包含反向文本的节点。它按预期工作,但只能工作一次。当我尝试再次运行它以将其反转回来时,我在控制台中遇到错误,我不知道为什么:

TaggedEventTracker.js:56 Uncaught TypeError: Cannot read property 'dataset' of null
    at e.findNearestZjsOrAElement (TaggedEventTracker.js:56)
    at e.findNearestZjsOrAElement (TaggedEventTracker.js:63)
    at e.trackTaggedEvent (TaggedEventTracker.js:73)
    at HTMLDocument.<anonymous> (TaggedEventTracker.js:17)

代码:

let paragraphs = document.querySelectorAll('p');

paragraphs.forEach(para => {
   para.onclick = function(evt) {
       updateText(evt.target)
   }
})


function updateText(target) {

     let node = target;

     let nodeText = target.innerHTML;

     let newEl = document.createElement('p');
     
     newEl.innerHTML = [...nodeText].reverse().join("");
     node.parentNode.replaceChild(newEl, node);
}
2个回答

为什么要创建新节点来替换旧节点?您只需替换原始元素的 innerHTML 即可。

替换元素时,它们的事件跟踪器似乎已损坏。

此外,通过替换节点,您还可以替换与其关联的事件处理程序。

let paragraphs = document.querySelectorAll('p');

paragraphs.forEach(para => {
   para.onclick = function(evt) {
       updateText(evt.target)
   }
})


function updateText(target) {
     target.innerHTML = [...target.innerHTML].reverse().join("");
}
<p>`123456789</p>
<p>`123456789</p>
<p>`123456789</p>

如果您想保留原始功能并仍然替换文本,您将需要克隆节点并附加新的事件处理程序。

let paragraphs = document.querySelectorAll('p');

paragraphs.forEach(para => {
   para.onclick = function(evt) {
       updateText(evt.target)
   }
})


function updateText(target) {

     let node = target;

     let nodeText = target.innerHTML;

     let newEl = target.cloneNode();
     
     newEl.innerHTML = [...nodeText].reverse().join("");
     node.parentNode.replaceChild(newEl, node);
     
    newEl.onclick = function(evt) {updateText(evt.target)}
}
<p>12233</p>
<p>x3332233</p>
imvain2
2020-12-10

如果您想在其中交换文本,这就是您所需要的。不要使用 innerHTML,而要使用 textContent。

let paragraphs = document.querySelectorAll('p');

paragraphs.forEach(para => {
   para.onclick = function(evt) {
       updateText(evt.target)
   }
})


function updateText(target) {

     let node = target;

     node.textContent =  [...target.textContent].reverse().join("");
}
Krystian Sitek
2020-12-10