5、模块化开发

263 阅读2分钟

1、高级单例模式

高级单例模式:创建一个命名空间(模块名)接收闭包中返回的相关信息,实现把闭包中的某些信息暴露出来,供其它的闭包调用;

(1)、代码示例

	/* let module1 = (function () {
		let name = '哈哈';

		function query() {

		}

		function fn() {
			console.log('FN');
		}

		return {
			query: query
		}
	})();


	let module2 = (function () {
		function fn() {
			console.log('FN2');
		}
		module1.query();
		return {};
	})(); */
  
  

(2)、代码示例

<script>
	let utils = (function () {
		return {
			// ...
		}
	})();

	let wetherModule = (function () {
		// ...自己的方法
		return {
			init() {
				// ...按照业务顺序逐一加载对应的方法
			}
		}
	})();
	wetherModule.init();

	// ...
</script>

2、AMD

moduleA.js

/* 
 * AMD思想中,模块的定义基于 define 完成
 *   define([name]?,[dependence]?,[factory])
 */
define(function () {
    // 任意数求和
    function sum(...args) {
        let len = args.length;
        if (len === 0) return 0;
        if (len === 1) return args[0];
        return args.reduce((total, item) => {
            return total + item;
        });
    }

    // 把指定的方法暴露到外面
    return {
        sum
    };
});

moduleB.js

/* AMD思想需要在定义新的模块之前,把依赖的模块事先导入可以 */
define([
    'moduleA'
], function (moduleA) {
    //=>moduleA存储的就是 'js/lib/moduleA' 这个模块导出的内容
    function average(...args) {
        let len = args.length;
        if (len === 0) return 0;
        if (len === 1) return args[0];
        return (moduleA.sum(...args) / args.length).toFixed(2);
    }
    return {
        average
    }
});

main.js

require.config({
    baseUrl: 'js/lib'
});

/*
 * AMD中导入某一个模块基于 require  
 *   require([dependence],[callback])
 */
require([
    'moduleB',
    // 'moduleA'
], function (moduleB) {
    let result = moduleB.average(10, 20, 30, 40, 50);
    console.log(`平均数是:${result}`);

    // result = moduleA.sum(10, 20, 30, 40, 50);
    // console.log(`和是:${result}`);

自己实现AMD规范

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <!-- IMPORT CSS -->
</head>

<body>
    <!-- IMPORT JS -->
    <script>
        let factories = {};

        /* 课后思考:define也需要设置依赖? */
        function define(moduleName, factory) {
            factories[moduleName] = factory;
        }

        function require(dependence, callback) {
            dependence = dependence.map(item => {
                return factories[item]();
            });
            callback(...dependence);
        }

        define('moduleA', function () {
            return {
                fn() {
                    console.log('moduleA');
                }
            };
        });
        define('moduleB', function () {
            return {
                fn() {
                    console.log('moduleB');
                }
            };
        });

        require(['moduleA', 'moduleB'], function callback(moduleA, moduleB) {
            moduleA.fn();
            moduleB.fn();
        });
    </script>
</body>

</html>

3、 CommonJS

moduleA.js

/*
 * require 导入模块
 * module.exports 导出模块中的方法 
 */
function sum(...args) {
    let len = args.length;
    if (len === 0) return 0;
    if (len === 1) return args[0];
    return args.reduce((total, item) => {
        return total + item;
    });
}

module.exports = {
    sum
};

moduleB.js

/*
 * 每一次REQUIRE都会先把moduleA执行一遍,把它基于
module.exports导出的对象克隆一份给moduleA变量
 */
let moduleA = require('./moduleA');

function average(...args) {
    let len = args.length;
    if (len === 0) return 0;
    if (len === 1) return args[0];
    return (moduleA.sum(...args) / args.length).toFixed(2);
}
module.exports = {
    average
};

main.js

// ....
let moduleB = require('./moduleB');
console.log(moduleB.average(10, 20, 30, 40, 50));

// ...
let moduleA = require('./moduleA');
console.log(moduleA.sum(10, 20, 30, 40, 50));

/*
 * CMD相对于AMD来讲,不需要前置依赖,什么时候用到,什么时候导入即可,而且Node环境下的CommonJS规范中,会把每一次导入的模块做缓存(后期再重新导入直接把上一次导入拷贝的结果复制一份过来即可) 
 */

 /*
  * ES6Module和CommonJS具备相同的机制:避免重复导入
  *   import  导入
  *   export / export default  导出
  * 
  * 特点:我们会在当前模块最开始的位置,基于import把所有依赖模块导入进来
  *  
  * CommonJS是运行时加载 ,ES6Module(在项目中一般配合webpack来使用)是在编译时处理
  */
  

4、UMD规范

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <!-- IMPORT CSS -->
</head>

<body>
    <!-- IMPORT JS -->
    <script>
        (function (global, factory) {
            if (typeof module === "object" && typeof module.exports === "object") {
                //... NODE环境下基于CommonJS规范实现的
            } else {
                //... 浏览器端运行
            }
        })(typeof window !== "undefined" ? window : this, function (window, noGlobal) {
            // ...
        });
    </script>
</body>

</html>