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

标签 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 导入 slick-carousel。我有一个带有横幅轮播和推文轮播的单页网站。我应该如何检查这些元素是否存在并初始化 2 个单独的轮播?

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

编辑

以我当前的工作流程为例,我定义了一个站点对象,该对象具有多个重用的静态变量和一些跨站点重用的项目,例如动画变量、对窗口的引用、自动更新变量以访问视口(viewport)属性等。

然后在每个构建的网站独有的单独文件中,我有一个主文件,我在其中为网站上实现的每个功能 block 创建单独的“模块”。利用页面中包含的 jQuery 和纯 JavaScript 插件以及实用程序和主要 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);

最佳答案

不要以“一切都是全局”的方式思考。全局范围是最大的 js 设计错误之一。例如:

    var name = 1;
    console.log(name + 1); // 2, right? No, try it ...

我不认为全局范围完全没用,但它的用例非常有限。您应该将其视为网页/服务器状态。这意味着在最好的情况下它不应该包含任何代码(=函数)。您向全局范围公开的功能(代码)越多,您就越有可能在两个脚本之间产生错误的推断,而这些错误确实很难发现。相反,您的代码应该封装自己。它应该尽可能少地向全局范围公开和更改。这意味着如果您想在页面的两个不同文件之间共享特定功能(例如 menu.jsslider.js 都需要一个 Button class) 那么这个功能应该进入一个模块,然后由两个脚本导入。所以每个单独的文件都应该在顶部有导入,在末尾有导出,并且应该封装自己:

import {functionality1, functionality2} from "module";

let somevariable; // variables declared with let or const do not appear on the global scope, although they are "global"

不要害怕在同一页面的不同文件中多次导入同一模块。模块只加载一次,并且使用 tree shaking(Webpack 等大多数 Bundler 都这样做),仅包含大型模块中的几个功能可能甚至不会加载整个大型模块,而只会加载其中的几个 block 。

关于javascript - 将全局导入模块模式转换为 ES6 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47552610/

相关文章:

reactjs - JS引用最佳实践? ES6/React——单引号、双引号、反引号?

ecmascript-6 - 有没有与 ES6 配合良好的代码复杂性计量工具?

javascript - contentEditable 仅在关闭并重新打开浏览器后工作

javascript - 在 ReactJS 中重新渲染 child 3 次是否可以接受?

javascript - 查询Internet Explorer单个选项卡的内存使用情况

javascript - npm install 超过了最大调用堆栈大小

typescript - Jest : Failed to parse the TypeScript config file

node.js - 在 npm 和 git 中同步版本管理

javascript - 通过 POST 调用 Rails 函数

javascript - 如何使用通用的单个提交按钮提交多个表单时创建单个请求