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定义的模块必须要有返回值

  • 相关阅读:
    java基础知识回顾之javaIO类---InputStreamReader和OutputStreamWriter转化流
    java基础知识回顾之javaIO类---FileInputStream和FileOutputStream字节流复制图片
    基本知识《一》继承初始化过程
    java调用matlab函数
    Dubbo基础篇-zookeeper安装(单点)
    《转》从0到100——知乎架构变迁史
    算法
    【转】基于LDA的Topic Model变形
    《转》探寻微博背后的大数据原理:微博推荐算法简述
    一个完整推荐系统的设计实现-以百度关键词搜索推荐为例
  • 原文地址:https://www.cnblogs.com/alice626/p/4955961.html
Copyright © 2011-2022 走看看