当您使用外部 JS 或 jQuery 插件时,可能会出现此错误。说说我的情况吧。
问题描述
在我的 React 项目中,我在页面上有一些链接,每个链接都会打开一个带有一些信息的模式和一个带有图像的滑块。每个链接在滑块内都有自己的一组图像。但我有单一模式,每个链接都是一样的。
模态的数据存储在一个状态变量中,我会在每次链接点击时更改其内容(在每次打开模态时):
const initialData = { title: "", intro: "" }; // here is some empty structure of object properties, we need it for the modalResponse initialization
const [modalData, setModalData] = useState(initialData);
// ...
<div id="MyModal">
<div className="title">{modalData.title}</div>
<div className="intro">{modalData.intro}</div>
<div>{modalData.sliderHtml}</div>
</div>
当我使用setModalData() 打开模式时,我会用一些新数据填充modalData。 modalData.sliderHtml 中的 HTML 代码类似于这样的结构:
<div class="carousel">
<div class="item"><img src="first.jpg" /></div>
<div class="item"><img src="second.jpg" /></div>
<div class="item"><img src="third.jpg" /></div>
</div>
当模态打开时,我调用一些 jQuery 代码来初始化滑块:
useEffect(() => {
$('.carousel').initCarousel({
// some options
});
}, [modalData]);
然后用户可以关闭模式并单击下一个链接。滑块必须由一组新图像填充。但我得到了错误:Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
错误原因
问题的原因在于 jQuery 插件在初始化期间改变了 html 的结构。 它在 .carousel 父级内创建了一些新块(向左/向右箭头,导航点等)。它会将所有.item 子代移动到新的.items 块内!插件初始化后得到这样的html结构:
<div class="carousel">
<div class="dots">...</div>
<div class="arrows">...</div>
<div class="items">
<div class="item"><img src="first.jpg" /></div>
<div class="item"><img src="second.jpg" /></div>
<div class="item"><img src="third.jpg" /></div>
</div>
</div>
当 React 尝试更改 modalData.sliderHtml 的内容时,它会执行一些神奇的 DOM 操作来移除旧结构。其中一个操作是removeChild 方法,但在父.carousel 中找不到旧的.item 元素,因为插件将它们移动到新的.items 元素中。所以,我们得到了错误。
错误修复
我开始在每次模态关闭时将modalData内容改回initialData结构。
useEffect(() => {
$('#MyModal').on('hidden.bs.modal', function (e) {
setModalData(initialData);
})
}, []);
所以,modalData.sliderHtml 中的所有 html 结构再次被初始的空数据填充,我们在新链接点击时不会收到错误。