【发布时间】:2019-01-10 19:01:37
【问题描述】:
我有一个与 Next.js 框架的工作方式有关的问题。 (但这类似于任何具有动态内容加载的 React 应用)
当 GTM 脚本加载时,它会将事件绑定到 DOM 元素。
GTM 脚本应该工作一次,并且对动态 DOM 加载不友好,因为它不会将事件绑定到新添加的 DOM 元素。
例如,如果您从页面 A 导航到页面 B,您会保留公共元素(页眉、页脚等)的事件,但主要内容已更改,并且没有 GTM 事件绑定到这些元素。
为了防止这种情况,我入侵了 GTM 并让它相信它还没有被初始化。因此,在每次客户端导航时,它都会再次绑定所有事件。
Router.onRouteChangeComplete = () => {
if (isBrowser() && typeof window.gtag !== undefined) {
ga_pageview();
// XXX Destroy all data of GTM, which will make it refresh all bindings (events) the next time GTM.initialize is called
// This is a hack to make GTM works with SPA, because otherwise events don't trigger because DOM events are removed when Next.js load dynamic parts of the DOM
delete window.google_tag_manager;
}
};
由于这个 hack,我的事件被触发了。 但是,现在 GTM 将这些事件绑定到未更改多次的部分,并最终为同一次点击触发 3 个相同的事件。
我试图找出防止它的方法,但我没有看到任何好的或简单的解决方案。
【问题讨论】:
-
GTM 脚本将事件绑定到文档,而不是单个元素,并通过事件冒泡和检查事件目标来捕获它们。因此,它应该与新创建的元素一起使用。如果没有,则说明其他问题(例如,阻止事件冒泡)。
-
有趣,我会研究一下,谢谢反馈
-
如果我在初始化 gtm 的站点上的 Chrome 控制台中执行
getEventListeners(document).click.forEach(listener=>console.log(listener)),我确实可以看到名为“e”的函数被绑定为“点击”事件侦听器。在我正在查看 gtm 侦听器的网站上,点击侦听器数组中的“第一个”。所以我可以通过document.removeEventListener('click',getEventListeners(document).click[1].listener,false);删除它理论上你可以在类似的事情之后删除多余的听众。但是...看来getEventListeners是Chrome 独有的实用功能。 -
有趣的相关讨论在这里:github.com/whatwg/dom/issues/412
标签: javascript google-tag-manager next.js