在看内容之前,我们需要来了解一下目前前端的形式。很久之前在一份简历中,看到这样一句话“推崇前端模块化及组件化”。而目前前端的需求也正如次。如果你有了解vue,react等前端流行框架,那么无论是那一个,都是组件为主。个人感觉vue会更舒服,包含了 template、script、css 的 *.vue文件用起来得心应手。说远了,我们接下来了解前端模块化。
1.模块
我们先来看看什么是模块,谈起模块就要从最根本的作用域开始说起。js的作用域是“函数级作用域”
function fn1() { var num = 10; } function fn2() { var num = 20; } window.fn1(); window.fn2();
上面的代码可以理解为最基本的模块,当然,这样的代码是不行,毕竟太污染全局变量了。
那么如果修改呢?看下面代码
var myModule = { num:10, str:"iwen", fn1:function () { console.log(this.num); }, fn2:function () { console.log(this.str); } }; myModule.num = 20; myModule.fn1();
将属于一个模块的内容放入到一个对象中,这样很好解决了污染问题。当大家看到
myModule.num = 20;
的时候,发现外部可以随意修改内部成员。所以这样写不太合适。
那么我们在看下面的代码:
var myModule = (function () { var num = 10; var str = "iwen"; function fn1() { console.log(num); } function fn2() { console.log(str); } return{ fn1:fn1, fn2:fn2 } })(); myModule.fn1();
看到这里,就解决了外部修改内部成员的问题。在进一步加强
看下面代码:(放大模式)
var module1 = (function () { var num =10; var str = "iwen"; function getName() { return str; } return { getName:getName } })(); var module2 = (function (module1) { module1.setName = function () { }; return module1; })(module1); console.log(module2.getName());
这样的好处是每一个module只处理当前相关的内容,我们来在进一步
看下面代码:(宽放大模式)
var module1 = { num:10, str:"iwen", fn1:function () { console.log(this.num); }, fn2:function () { console.log(this.str); } }; module1 = null; var module2 = (function (module1) { module1.getName = function () { }; return module1; })(window.module1 || {}); console.log(module2);
与放大模式相比,宽放大模式可以传入空对象。如果我们需要引入第三方相关类库怎慢呢?
看下面代码:
var module = { num:10 }; var module1 = (function ($,module) { function getNum() { console.log(module.num); } function getJQ() { console.log($("div")); } return{ getJQ:getJQ, getNum:getNum } })(jQuery,module); module1.getJQ(); module1.getNum();
下面我们在来研究一下私有与共有的问题:
var module1 = (function () { var num =10; var str = "iwen"; function getName() { return str; } return { getName:getName } })(); var module2 = (function (module1) { module1.setName = function () { }; return module1; })(module1); console.log(module2);
上面的代码,大家好好思考一下。
2.接下来了解一下“模块化”
受到了NodeJS的Commonjs规范影响,在浏览器端也开始流行模块化,模块化单独说起来有点麻烦。我们还是来引入第三方吧,知名被常用到目前有一下
(1)require.js
(2)sea.js
首先我们来看一下Commonjs规范,具体代码看下面:
module.js:
function demo() { console.log("demo"); } function demo2() { console.log("demo2"); } module.exports = { demo:demo, demo2:demo2 }
demo.js
var module1 = require("./module1"); module1.demo(); module1.demo2();
以上代码,需要Node环境来进行执行。关于Node并非本章内容,在这里不过多说明。
接下来看一来require.js。
AMD 是 RequireJS 在推⼴过程中对模块定义的规范化的产出
requireJS主要解决问题:
(1)实现js⽂件的异步加载,避免⽹⻚失去响应
(2)管理模块之间的依赖性,便于代码的编写和维护
具体实现:
(1)引入
<script src="js/libs/require.js" data-main="js/main.js">
(2)编写主入口文件:main.js
//require的配置 require.config({ //定义基础路径 baseUrl:"js", //加载文件路径 paths:{ "jquery":"libs/jquery-3.2.1", "getName":"app/getName" } }); require(["jquery","getName"],function ($,getName) { });
(3)编写自己的模块
define(function () { function setDiv() { var div = document.getElementsByClassName("div").item(0); div.innerHTML = "嘿嘿"; } setDiv(); });
以上为require.js基础内容,更多内容请参考官方API进行学习
具体实现效果可以参考这里,代码没有压缩,可直接看。如果有需要联系邮箱:iwen@iwens.org
接下来看一下sea.js,到现在,seajs已经不再开发及维护,只能为那些一直在使用sea.js的童鞋标示默哀了。
CMD:seajs在推广过程中对模块定义的规范化产出
(1)引入
<script src="js/sea.js">
(2)加载模块
seajs.config({ base:"./js/", alias:{ "getName":"getName", "jquery":"jquery-3.2.1" } }); seajs.use("main");
(3)创建模块
define(function (require,exports,module) { //加载文件 require.async(["jquery","getName","setName"],function ($,getName,setName) { console.log(setName.setName()); }) });
接下来还是要说一下,总有一些面试官会问,你知道“CMD和AMD的区别么?”,脑子秀逗的人喜欢这么问。哈哈,原谅我吧,我的神。
4.AMD和CMD的区别
AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
CMD推崇就近依赖,只有在⽤到某个模块的时候再去require
以上内容就是模块化的基本内容。本文为作者原创,转载请注明出处,谢谢。