将全局导入模块模式转换为ES6模块

时间:2017-11-29 12:13:14

标签: javascript npm ecmascript-6 es6-modules

因此,在过去的几年里,我一直在使用javascript的全局导入方法。通常使用一组实用程序函数包装并传递给另一个站点模块,该模块包含每个Web功能的单独功能;

(function(m, u, ui, w, a, $){

    // Example Module
    m.example = function(){
        // Do stuff, the m.example module gets auto initialized.
};

})(Site.modules = Site.modules || {}, Site.utils, Site.ui, Site.w, Site.anim, jQuery);

在这个示例中,我传递了我们添加的模块,实用程序,用户界面对象(主要是别名gsap)和其他类似jQuery的东西。

正如你所看到的,它可能会变得很大,特别是在具有大量功能的大型网站上。

我想转到ES6和NPM,虽然我已经看过如何制作模块的文章和示例,如何导入模块,使用NPM引入模块我不能找到一个关于实际将它们全部拉到一起的例子或文章。

举个简单的例子。我用NPM导入光滑轮播。我有一个单页网站,有一个横幅轮播和一个推文轮播。我应该如何检查存在的元素并初始化2个单独的轮播?

使用匿名闭包我只需要一个单独的自动启动函数来查找DOM元素,然后使用不同的选项初始化轮播。

修改

对于我当前工作流程的示例,我定义了一个站点对象,该对象具有多个重用的静态变量以及在整个站点中重用的一些项目,如动画变量,窗口​​引用,自动更新变量以访问视口属性等。

然后,在每个构建的网站独有的单独文件中,我有一个主文件,我在其中创建单独的'模块'对于网站上每个实现的功能块。利用页面上包含的jQuery和普通javascript插件以及utils和main js文件。

utils.js

jQuery(document).ready(function($) {
    Site.init();
});


var Site = (function($) {

    // DOM caching
    var win = window;

    // Globals
    var w = {
        width:  win.innerWidth,
        height: win.innerHeight,
        scroll: win.pageYOffset
    };

    var ui = {
        fast: 0.2,
        slow: 0.4,
        step: 0.03,
        easeout: Power4.easeOut,
        easein: Power4.easeIn
    };

    function updateGlobals(){
        w.width  = win.innerWidth;
        w.height = win.innerHeight;
        w.scroll = win.pageYOffset;
    }

    win.addEventListener('resize', updateGlobals, true);
    win.addEventListener('scroll', updateGlobals, true);
    win.addEventListener('load', updateGlobals, true);

    return {
        init: function(){

            for (var prop in this.modules) {
                if ( this.modules.hasOwnProperty(prop) ) {
                    this.modules[prop]();
                }
            }

            for (var props in this.autoInits) {
                if ( this.autoInits.hasOwnProperty(props) ) {
                    var $selector = $(props);

                    if ($selector.length) {
                        this.autoInits[props]($selector);
                    }
                }
            }
        },
        ui: ui,
        w: w
    };

})(jQuery);

main.js

(function(m, $){

    m.homepageCarousel = function(){
        var element = $('.js-homepage-carouel');

        $(element).slick({
            dots: true,
            speed: 500,
            arrows: false
        });
    };

    m.productsCarousel = function(){
        var element = $('.js-products-carouel');

        $(element).slick({
            dots: false,
            speed: 500,
            arrows: true
        });
    };

    m.showcookieNotice = function(){
        ... example check cookies for marker and show cookie notice if not present.
    }

    ... rest of the websites js, maps, menus, custom reused items etc

})(Site.modules = Site.modules || {}, jQuery);

1 个答案:

答案 0 :(得分:0)

不要想在"一切都是全球性的"办法。全球范围是最大的js设计错误之一。 E.g:

var name = 1;
console.log(name + 1);

我不认为全球范围完全无用,但其使用范围非常有限。您应该将其视为网页/服务器状态。这意味着它应该在最好的情况下不包含代码。您向全局范围公开的功能(代码)越多,您在两个脚本之间的推断就越有可能,并且这些错误很难被发现。所以你的代码应该封装自己。它应尽可能少地暴露和改变到全球范围。这意味着如果您想在页面的两个不同文件之间共享某个功能(例如 menu.js slider.js 都需要按钮 class)然后这个功能应该进入一个模块,然后由两个脚本导入。因此,每个单独的文件应该在顶部导入导入,在最后导出导出,并且应该封装自己:

import {functionality1, functionality2} from "module";

{ //encapsulation
  let somevariable;
  //... your code
}

不要害怕在同一页面上的不同文件中多次导入同一个模块,js引擎会对其进行优化。