Vaadin14集成PayPal出现Detected container element removed from DOM报错
问题根因
你遇到的报错是普通Spring环境下Vaadin默认开启了全局ShadyDOM强制模拟,PayPal JS SDK不兼容该Polyfill的Shadow DOM模拟逻辑,而Spring Boot的Vaadin Starter默认未开启该强制配置,因此运行正常。
可行解决方案
方案1:调整ShadyDOM全局配置(优先推荐,改动最小)
修改你原有页面初始化配置,仅在浏览器不支持原生Shadow DOM时才开启ShadyDOM模拟,既兼容PayPal SDK,也不会触发浏览器密码自动填充失效的问题:
@Override public void configurePage(InitialPageSettings settings) { settings.addMetaTag("mobile-web-app-capable", "yes"); settings.addMetaTag("apple-mobile-web-app-capable", "yes"); settings.addMetaTag("apple-mobile-web-app-status-bar-style", "black"); settings.addInlineWithContents( InitialPageSettings.Position.PREPEND, "window.customElements=window.customElements||{};" + "window.customElements.forcePolyfill=true;" + "window.ShadyDOM = window.ShadyDOM || {};" + "window.ShadyDOM.force = !window.ShadyDOM.isSupported;", InitialPageSettings.WrapMode.JAVASCRIPT); }
目前主流浏览器均已支持原生Shadow DOM,该配置几乎不会影响现有功能兼容性。
方案2:保留全局ShadyDOM配置,调整PayPal渲染逻辑
如果必须保留ShadyDOM.force=true的全局配置,可通过将PayPal按钮先渲染到不受ShadyDOM管控的全局节点,再转移到组件内的方式兼容:
- 先在页面初始化时新增一个全局隐藏容器,不受ShadyDOM管控:
@Override public void configurePage(InitialPageSettings settings) { // 原有其他配置不变 settings.addInlineWithContents(InitialPageSettings.Position.PREPEND, "<div id='paypal-global-container' style='display: none;'></div>", InitialPageSettings.WrapMode.NONE); }
- 修改
paypal-view.js中的按钮渲染逻辑:
将原有渲染代码
buttons.render(this.shadowRoot.getElementById("paypal-button-to-display")) .then(() => { hasRendered = true; })
替换为
const globalContainer = document.getElementById('paypal-global-container'); buttons.render(globalContainer).then(() => { const targetContainer = this.shadowRoot.getElementById("paypal-button-to-display"); targetContainer.innerHTML = ''; targetContainer.appendChild(globalContainer.firstChild); hasRendered = true; }).catch((err) => { console.log(err); return; });
组件销毁时注意清空全局容器内容,避免重复渲染报错。
方案3:修复现有代码拼写错误
你的hello-world-view.ts中存在标签拼写错误,自定义组件注册名为paypal-element,实际使用时写成了<paypal-elementt>多了一个字母t,该错误也会导致组件渲染异常,请先修正该错误。
内容的提问来源于stack exchange,提问作者Thang Le
相关产品推荐
相关产品推荐

