使用 ES6 模块重新导出全局变量
Re-export global variables with ES6 modules
我正在将JS脚本迁移到ES6模块。客户端代码的常见模式是将跟踪信息推送到 window
对象上的全局数组。一个具体的例子是GTM window.dataLayer
数组。
我想将这些全局变量抽象到 ES6 模块中,而不是指示 linter 用 /* global dataLayer */
忽略它们,因为它使代码更容易理解。我的第一个尝试是创建这样的垫片:
export default window.dataLayer;
但是,如"实现视图"一节中所述,上述代码等效于:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
因此,每个模块中的window.dataLayer
数组将是原始window.dataLater
数组的副本:当 GTM 异步引导时,它不会看到从模块推送的事件,因为只有本地*default*
才会有这些事件。
ES6 模块处理此类全局变量的推荐方法是什么,它不涉及像使用 Proxy 那样的重量级解决方案?在模块化系统中有很多全局变量确实感觉很糟糕。
与您在问题中描述的相反,处理此问题的正确方法是:
/* 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 导入将只读引用传递给导出,因此它不是要导入的数组的副本,而是在数据层中创建和导出的数组.js。
但是棘手的部分是,您必须修改Google跟踪代码管理器容器代码段,使其在加载后不会立即运行,而是仅在所有可能修改dataLayer
脚本运行后运行。
如果要将 GTM 容器代码段作为模块单独加载,则可能需要先导入所有可能修改 dataLater 的脚本(并确保该部分实际运行),然后再调用代码段。
像这样:
/* 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')
}
但是,你知道这并不是如何做到这一点的真正解释,只是一个想法,我不知道什么不同的东西可能会添加到dataLayer,并且由于您正在转向异步模块模式,因此您必须了解异步运行所有这些脚本将如何改变您使用GTM系统的方式, 这显然是写成使用全局变量同步运行的。
我想知道谷歌是否会很快用现代JavaScript更新这些东西,或者是否有一个更模块化的选项可用。
如果您不知道,我应该提到:
截至今天(2016 年 1 月),许多(大多数)ES6/ES2015 功能(包括模块)在浏览器中不可用,因此您需要某种构建或加载器来使这些东西在浏览器中工作(如 webpack、browserify、stealjs、jspm 或带有 babel 或 tracuer 之类的东西)
http://stealjs.com/可能是最容易上手的。
- 全局变量和全局对象的属性之间有什么区别吗
- delete关键字在全局变量上的不同行为
- 在javascript函数中设置全局变量
- 如何将getJson的响应保存在全局变量中
- 从Javascript方法返回全局变量
- AngularJS中的封装窗口全局变量
- javascript隐式全局变量
- 如何从onclick函数设置全局变量并将其传递给另一个JS文件
- 如何使全局变量仅特定于该文件
- 在page.open()-PhantomJS中无法访问全局变量
- 可以在模块中运行.导出访问模块中的全局变量
- 为函数中的现有数组(全局变量)分配新值不起作用.为什么
- 默认导出为全局变量 Typescript 1.8 --module UMD
- 使用 ES6 模块重新导出全局变量
- 每次在 JavaScript 中运行函数时创建一个新的唯一全局变量
- 全局变量在新的弹出窗口中是未定义的,而它们是预先定义的
- 如何从browserify/babelify导出全局变量,以便在没有browserfy的情况下在项目中使用
- twitter bootstrap-Xpages,需要全局变量将字段的新ID映射回字段的原始ID,以便可以与客户端Jav
- 如何在新的Function上下文中访问全局变量
- 全局变量-用新函数构造的javascript函数不能调用其他函数