我正在将 JS 脚本迁移到 ES6 模块。客户端代码的一种常见模式是将跟踪信息推送到 window
对象上的全局数组。一个具体的例子是 GTM window.dataLayer
数组。
我想将这些全局变量抽象到 ES6 模块中,而不是使用 /* global dataLayer */
指示 linter 忽略它们,因为它使代码更容易理解。我的第一次尝试是创建这样的垫片:
export default window.dataLayer;
但是,正如解释的here在“实现 View ”部分,上述代码等同于:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
因此,每个模块中的 window.dataLayer
数组将是原始 window.dataLater
数组的副本:当 GTM 异步引导时,从它不会看到模块,因为只有本地 *default*
才会有这些事件。
使用 ES6 模块处理此类全局变量的推荐方法是什么,它不涉及像使用代理这样的重量级解决方案?在模块化系统中有很多全局变量确实让人感觉很糟糕。
最佳答案
与您在问题中描述的相反,处理此问题的正确方法是:
/* data-layer.js */
window.dataLayer = [];
export default window.dataLayer;
...以及任何需要推送到“dataLayer”数组的模块,只需要像这样的东西:
import dataLayer from 'data-layer';
// ... some code I assume
dataLayer.push({
'pageCategory': 'signup',
'visitorType': 'high-value'
});
因为 ES6 导入将只读引用传递给导出,所以它不是您正在导入的数组的副本,而是在 data-layer.js 中创建和导出的数组。
但棘手的部分是,您必须修改 Google 跟踪代码管理器容器代码段,使其不会在加载后立即运行,而是仅在加载完所有脚本后运行可以修改已经运行的dataLayer
。
如果您要将 GTM Container Snippet 作为一个模块单独加载,您可能需要先导入所有可能会修改数据的脚本(并确保该部分实际运行),然后再导入调用代码段。
类似于:
/* gtm-container.js */
import 'this';
import 'that';
import otherThing from 'the-other-thing'; // lets assume it returns a promise
import dataLayer from 'data-layer'l
otherThing.then(value => {
invokeSnippet()
})
.catch(err => {
handleError(err);
});
function invokeSnippet() {
(function(w,d,s,i){dataLayer.push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX')
}
但是,你知道这并不是对如何做到这一点的真正解释,只是一个想法,我不知道可以向数据层添加什么不同的东西,并且因为你正在转向异步模块模式,你将拥有了解异步运行所有这些脚本将如何改变您使用 GTM 系统的方式,清楚地编写该系统是为了使用全局变量同步运行。
我想知道 Google 是否会很快用现代 JavaScript 更新这些东西,或者是否有更模块化的选项可用。
如果您不知道,我应该提一下:
许多(大多数)ES6/ES2015 功能,包括模块,截至今天(2016 年 1 月)在浏览器中不可用,因此您需要某种构建或加载器来制作这些东西在浏览器中工作(比如 webpack、browserify、stealjs、jspm,或者带有 babel 或 tracuer 的东西)
http://stealjs.com/可能是最容易上手的。
关于javascript - 使用 ES6 模块重新导出全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34862340/