zoukankan      html  css  js  c++  java
  • Javascript 模块化编程 --RequireJs

    什么是模块化

    模块就是实现特定功能的一组方法,常见的几种js写法

    • 原始写法
      function A() {
    
            }
    
     function B() {
                
      }

     上面函数A()和B()组成一个模块,使用的时候直接调用就行了

    缺点: “污染”了全局变量,模块成员之间没有直接的联系。

    •   对象写法
    var module= {
             count:1,
             A: function() {
             },
             B: function() {
             }
           }

    这种写法把变量count和函数A和 B 都封装到了module中,使用的时候直接调用,例如:

    Module.A();

    缺点:这种做法暴露了模块成员,内部的变量可以被外部改写,例如:

    Module.count=5

     

    • 立即执行函数写法
    var modulel = (function() {
                var count = 5;
                var A = function() {
                    console.log("function A");
                };
                var B = function() {
                    console.log("function B");
                };
                return {
                    A:A,
                    B:B,
                    count:count
                }
    
            })();
    •  放大模式

    如果一个模块很大,必须分成几个部分,则需要继承另外一个模块,则有必要使用“放大模式”

    var commonUtil = (function (util) {
    
                util.m1 = function () {
    
                    console.log("m1 function");
    
                };
                util.m2 = function () {
                    console.log("m2 function");
                };
    
                util.count = 5;
    
                return util;
    
            })(commonUtil);
    
            console.log(commonUtil.m1());
    
            console.log(commonUtil.count);
    •  宽放大模式
    var commonUtil = (function (util) {
                util.m1 = function () {
                   console.log("m1 function");
                };
                util.m2 = function () {
                    console.log("m2 function");
                };
    
                util.count = 5;
    
                return util;
    
            })(commonUtil || {});
    
            console.log(commonUtil.m1());
    
            console.log(commonUtil.count);

    与“放大模式”相比,“宽放大模式”就是立即执行函数可以是空对象

    为什么要用require.js

    最早的时候,所有的javascript都是写在一个文件中,代码越来越多,则分成了多个,例如:

    <script src="1.js"></script>
    <script src="2.js"></script>
    <script src="3.js"></script>
    <script src="4.js"></script>
    <script src="5.js"></script>
    <script src="6.js"></script>

    这样做的缺点:

    1)加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就越长

    2)必须保证加载的顺序,依赖最大的模块一定要放到最后加载 

    Require.js就是为了解决这两个问题: 

    1)   实现js文件的异步加载,避免网页失去响应

    2)   管理模块之间的依赖性,便于代码的编写和维护

    Require.js加载

    首先要到官方网站下载最新版本http://requirejs.org/docs/download.html放到Scripts目录下

    然后在页面加载,例如:

    <script src="Scripts/require.js"></script>

     加载这个文件也有可能造成网页失去响应,解决办法有两个,一是把它放在网页底部加载,另外一个是写成这样:

    <script src="Scripts/require.js" defer async="true" ></script>

    Async表示是异步加载,ie不支持这个属性,只支持defer,所以把defer也写上

    加载require.js之后,则是加载我们自己的代码了,假如我们自己的代码文件是main.js,则需要写成这样

    <script src="Scripts/require.js" data-main="Scripts/main.js"></script>

     data-main属性的作用是指定网页程序的主模板,就是网页的入口代码,有点像控制台程序的main()函数,所有的代码都是从这里开始运行

    模块的加载

    假如模块依赖’jquery’,’underscore’,’backbone’,则需要在require.config()方法中对这些模块进行配置

    我们可以把require.config()写在主模块main.js的头部,也可以新建一个require_config.js文件把这些配置写在这个文件中,然后在页面引用这个文件,例如:

    (function () {
        var baseurl = "/Scripts/";
        require.config({
            paths: {
                "jquery": baseurl+"jquery",
                "underscore": baseurl+"underscore",
                "backbone": baseurl+"backbone",
                "index":baseurl+"lib/index"
            },
    
            shim: {
                'underscore': {
                   exports: '_'
                },
    
                'backbone': {
                    deps: ['underscore', 'jquery'],
                    exports: 'Backbone'
                }
            }
    
        });
    })();

    如果某个模块在另外的主机上,也可以指定网址,例如:

    require.config({
            paths: {
                "jquery":”https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min”,    
            }
        });

    require.js加载的模块,必须按照AMD规范,用define()函数定义的模块。但有一部分函数库并不符合这种规范,这种模块则必须在require()加载前,用shim属性进行配置,shim属性是用来配置不兼容的模块。

    例如:

       shim: {
                'underscore': {
                    exports: '_'
                },
    
                'backbone': {
                    deps: ['underscore', 'jquery'],
    exports:
    'Backbone' } }

    其中

    1) exports表示输出变量名,即在模块外部调用的名称

    2) deps数组,表示该模块的依赖性

    主模块的写法

    require()函数接受两个参数,第一个参数是一个数组,表示所依赖的模块,第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数的形式传入该函数,而在回调函数中就可以使用这些模块了。

    例如:主模块依赖jquery,underscore和backbone这三个模块,main.js就可以这样写:

    require (['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {
       //some code here
    });

    require.js会先加载jQuery,underscore和backbone,然后再运行回调函数,主模块的代码就写在回调函数中

    AMD模块的写法

    require.js加载的模块,采用AMD规范,模块也必须按照AMD来写,就是模块必须采用特定的define函数来定义,例如math.js:

    define(function() {
                var add = function(x, y) {
                    return x + y;
                };
                return add;
            });

    然后在require_config.js的path中进行定义,例如:

    (function () {
    
        var baseurl = "/Scripts/";
    
        require.config({
    
            paths: {
                "math":baseurl+"lib/math"
            },
        });
    })();

    之后再在页面对这个math模块进行加载,如:

    require(['math'], function(math) {
               console.log(math.add(3,5));
            });

     例如利用require.js模块化写一个简单的banckbone例子,index.htm代码如下:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>我的第一个backbone的例子</title>
    </head>
    <body>
        <button id="check">新手报到</button>
        <ul id="world-list">
            
        </ul>
        <script src="../../Scripts/require.js" data-main="../../Scripts/lib/index.js"></script>
        <script src="../../Scripts/require_config.js"></script> 
        <script>
            require(['index'], function(indexView) {
                var app = indexView.AppView;
                var AppView = new app;
            });  
        </script>
    </body>
    </html>
    View Code

    require_config.js配置如下:

    (function () {
        var baseurl = "/Scripts/";
        require.config({
            paths: {
                "jquery": baseurl+"jquery",
                "underscore": baseurl+"underscore",
                "backbone": baseurl+"backbone",
                "index":baseurl+"lib/index"
            },
            shim: {
                'underscore': {
                    exports: '_'
                },
                'backbone': {
                    deps: ['underscore', 'jquery'],
                    exports: 'Backbone'
                }
            }
        });
    
    })();
    View Code

    index.js文件的代码如下:

    define(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {
        var listView = { 
            World: Backbone.Model.extend({
                name: null
            }),
            Worlds: Backbone.Collection.extend({
                initialize: function(models, options) {
                    this.bind("add", options.view.addOneWord);
                }
            }),
            AppView: Backbone.View.extend({
                el: $("body"),
                initialize: function() {
                    this.worlds = new listView.Worlds(null, { view: this });
                },
                events: {
                    "click #check": "checkIn"
                },
                checkIn: function() {
                    var world_name = prompt("请问你是哪里人");
                    if (world_name == "") world_name = "未知";
                    var world = new listView.World({ name: world_name });
                    this.worlds.add(world);
                },
    
                addOneWord: function (model) {
                    $("#world-list").append("<li>我是来自:" + model.get("name") + "的人!</li>");
                }
            })
        };
        return listView;
    });
    View Code

    define和require加载的区别

    Define和require在依赖处理和回调执行上是一样的,但是define回调的函数需要有return语句返回模块对象,这样define定义的模块才能被其他模块调用;require回调函数不需要有return语句。所以说define和require都可应用来加载和使用模块,但是define可以用来定义模块,用define定义的模块必须要有返回值

  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/alice626/p/4955961.html
Copyright © 2011-2022 走看看