• RequireJS初探


    什么是RequireJS?

    /* ---

    RequireJS 是一个JavaScript模块加载器。它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJS加载模块化脚本将提高代码的加载速度和质量。

    IE 6+ .......... 兼容 ✔
    Firefox 2+ ..... 兼容 ✔
    Safari 3.2+ .... 兼容 ✔
    Chrome 3+ ...... 兼容 ✔
    Opera 10+ ...... 兼容 ✔

    开始使用 或者看看 API

    --- */

    http://www.requirejs.cn/home.html

    https://github.com/jrburke/requirejs

    一句话, 它是为了JS模块化而生,是代码逻辑封装的手段,  目的是为了减少代码复杂度,提高代码可维护性, 满足设计上要求的高内聚+低耦合。

    为浏览器环境而生,提高js加载速度。

    为什么要有RequireJS?

    http://www.requirejs.cn/docs/why.html

    遇到的问题

    • Web sites are turning into Web apps
    • Code complexity grows as the site gets bigger
    • Assembly gets harder
    • Developer wants discrete JS files/modules
    • Deployment wants optimized code in just one or a few HTTP calls

    ---- 翻译 ----

    1、 web站点转变为 web应用

    2、代码复杂度随着站点的变大而增长

    3、组装(页面代码)更加困难

    4、开发者需要分离js文件和模块

    5、部署活动需要优化过的代码存储在一个文件中, 或者少些HTTP请求。

    解决方案:

    Front-end developers need a solution with:

    • Some sort of #include/import/require
    • ability to load nested dependencies
    • ease of use for developer but then backed by an optimization tool that helps deployment

    ---- 翻译 ----

    前端开发者需要一个满足如下条件的解决方案:

    1、一些类似 include import require 等经典模块方法

    2、有能力加载嵌套依赖

    3、对于开发者易用, 同时也可以被(用于部署的)优化工具支持。

    ---- 模块化进化史 -----

    原始

    -在一个页面还很简单的时候, 一个同事添加了一个js函数  function xx

    后由于新增需求, 另外一个同事处于另外目的, 添加了一个相同名称的函数 function xx, 内容实现不一样, 这样就悲剧了, 第一个同事实现的 函数被冲掉了, 因为它们都定义在 全局环境中。

    IIFE == imediately invoked function expression  立刻执行函数表达式

    组织规范要求, 每个人开发的相关内容做为一个模块, 必须放在一个IIFE的函数体中,

    (fuction(){

         funciton XX(){}

    })();

    这样两个同事开发代码都不会相互影响对方, 但是这样定义的函数, 不能再全局环境的其他代码中调用, 因为在IIFE中的函数只在其函数体中生效, 可以作为window一个属性开放出去,

    但是其仍然有个缺点, 就是两个模块之间的依赖无法体现, 如果后面一个同事的开发模块, 依赖前一个同事的, 这样后面同事写的代码必须在 前一个同事代码 之后, 否则就会调用失败。

    module时代

    随着web页面内容越来越大, 前端代码越来越复杂,且有复杂的代码依赖关系。 就需要今天的主题事物出场。

    AMD vs CommonJS

    模块化标准包括 commonjs和requirejs, requireJS满足AMD标准, 为啥采用AMD?

    因为主要是此标准为异步加载设计, 故适合浏览器远程加载若干模块的js文件。

    而commonjs标准,加载文件为同步模式, 一个一个执行, 适合加载本地文件, nodejs实现满足此标准。

    两个标准的详细描述见:

    http://www.commonjs.org/

    http://www.requirejs.org/docs/whyamd.html

    怎么使用RequireJS?

    http://requirejs.org/docs/api.html

    定义模块,新建一个文件, 按照api规范定义模块实现, 模块返回为对象

    //Inside file my/shirt.js:
    define({
        color: "black",
        size: "unisize"
    });

    如果还有些定制逻辑,则有可以使用函数,作为模块实现作用域:

    //my/shirt.js now does setup work
    //before returning its module definition.
    define(function () {
        //Do setup work here
    
        return {
            color: "black",
            size: "unisize"
        }
    });
     

    如果模块对其他模块有依赖

    //my/shirt.js now has some dependencies, a cart and inventory
    //module in the same directory as shirt.js
    define(["./cart", "./inventory"], function(cart, inventory) {
            //return an object to define the "my/shirt" module.
            return {
                color: "blue",
                size: "large",
                addToCart: function() {
                    inventory.decrement(this);
                    cart.add(this);
                }
            }
        }
    );

    模块也可以返回函数

    //A module definition inside foo/title.js. It uses
    //my/cart and my/inventory modules from before,
    //but since foo/title.js is in a different directory than
    //the "my" modules, it uses the "my" in the module dependency
    //name to find them. The "my" part of the name can be mapped
    //to any directory, but by default, it is assumed to be a
    //sibling to the "foo" directory.
    define(["my/cart", "my/inventory"],
        function(cart, inventory) {
            //return a function to define "foo/title".
            //It gets or sets the window title.
            return function(title) {
                return title ? (window.title = title) :
                       inventory.storeName + ' ' + cart.name;
            }
        }
    );

    还可以自定义模块名称

        //Explicitly defines the "foo/title" module:
        define("foo/title",
            ["my/cart", "my/inventory"],
            function(cart, inventory) {
                //Define foo/title object in here.
           }
        );

    DEMO

    定义了两个模块, 和一个app, 依赖两个模块, 调用并执行:

    https://github.com/fanqingsong/code-snippet/tree/master/web

    image

    one.js

    //Inside one.js:
    define(function() {
            return function(title) {
                return console.log('one module called');
            }
        }
    );

    two.js

    //Inside two.js:
    define(function() {
            return function(title) {
                return console.log('two module called');
            }
        }
    );

    app.js

    requirejs.config({
        //By default load any module IDs from ./
        baseUrl: './',
    });

    // Start the main app logic.
    requirejs(['one', 'two'],
    function   (one, two) {
        one();
        two();
    });

    demo.html

    <html>
    <head>
            <!--This sets the baseUrl to the "scripts" directory, and
                loads a script that will have a module ID of 'main'-->
            <script data-main="./app.js" src="./require.js"></script>
            <style>

            </style>
    </head>
    <body>
            <h1>hello world!</h1>
    </body>
    </html>

    打印:

    image

  • 相关阅读:
    putty如何退出全屏模式
    maven项目如何生成war文件
    使用web.xml方式加载Spring时,获取Spring context的两种方式
    Mybatis 示例之 SelectKey
    psql主主复制
    【转】angular使用代理解决跨域
    Error: EACCES: permission denied when trying to install ESLint using npm
    Run Code Once on First Load (Concurrency Safe)
    [转]对于BIO/NIO/AIO,你还只停留在烧开水的水平吗
    golang 时间的比较,time.Time的初始值?
  • 原文地址:https://www.cnblogs.com/lightsong/p/4719750.html
Copyright © 2020-2023  润新知