前端模块化

    xiaoxiao2023-03-24  1

    1.模块化编程

    1.1 ES5时代

    1.1.1 原生代码实现模块化

    1) 对象写法

    var module1 = new Object({     _count : 0,     m1 : function (){       //...     },     m2 : function (){       //...     }   });

    2) 立刻执行函数(Immediately-Invoked Function Expression,IIFE) or 匿名闭包

    var module1 = (function(){     var _count = 0;     var m1 = function(){       //...     };     var m2 = function(){       //...     };     return {       m1 : m1,       m2 : m2     };   })();

    这样可以很好的保护私有变量,通过return来设置公开的方法。缺点也有: 动态添加方法的时候比较麻烦,且无法修改内部私有变量. 3) 放大模式 or 宽放大模式(Loose augmentation) 如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用”放大模式”(augmentation)

    var module1 = (function (mod){     mod.m3 = function () {       //...     };     return mod;   })(module1);

    在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用”宽放大模式”

    var module1 = ( function (mod){     //...     return mod;   })(window.module1 || {});

    测试

    var moduleTest = ( function (mod){ var value1=0, privateName='smt'; function privateAddTopic(data) { // 这里是内部处理代码 console.log("内部函数"); console.log(data); } mod.name = privateName; mod.init=function(){ this.f1(); this.f3(); }; mod.f1=function(){ console.log("f1--hello"); };  mod.f2=function(){ console.log("f2--hello"); };   mod.f3=function(){ console.log("f3--hello"); };  mod.f4=function(){ console.log("f4--hello"); };  mod.f5=function(data){ privateAddTopic(data); };      return mod; })(window.moduleTest || {}); moduleTest.init(); moduleTest.f3(); moduleTest.f5("hello world"); console.log(moduleTest.name); moduleTest.name = 'zry'; //修改模块中的属性 console.log(moduleTest.name);

    1.1.2 CommonJS/AMD/CMD

    现代模块的基本思想实现如下:

    var myModules = (function Manager() { var modules = {}; //定义的模块保存在这个对象里面 function define(name, deps, impl) {//impl是implement的简写,实现的方法 for (var i = 0; i < deps.length; i++) { deps[i] = modules[deps[i]]; //从保存的对象中获取依赖的模块,注:依赖的模块,肯定已经被define()存放在modules对象中了。 } modules[name] = impl.apply(impl, deps);//如果此时的模块引入别的模块deps,就将deps作为impl实现的方法的参数 } /** * [get 通过名字获得模块] * @param {[type]} name [模块名] * @return {[type]} [完整独立模块] */ function get(name) { return modules[name]; } return { define: define, get: get }; })(); //测试 myModules.define("bar", [], function() { function hello(who) { return "hello " + who; } return { hello: hello }; }); myModules.define("foo", ["bar"], function(bar) { var n = 'zry'; function awe(who) { console.log(bar.hello(n).toUpperCase()); } return { awe: awe }; }); var bar = myModules.get("bar"); var foo = myModules.get("foo"); foo.awe();//HELLO ZRY

    * 1) CommonJS* node.js的模块系统,就是参照CommonJS规范实现的

    var math = require('math'); math.add(2,3); // 5

    第二行math.add(2, 3),在第一行require(‘math’)之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。

    这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于”假死”状态。这就催生AMD规范到来的背景。 * 2) AMD* AMD(Asynchronous Module Definition)是异步模块加载的意思。

    require([module], callback); require(['math'], function (math) {   math.add(2, 3); });

    主要有两个Javascript库实现了AMD规范:require.js和curl.js * 3) CMD*

    CMD(Custom Module Definition)通用模块加载 引入seajs文件

    <script type="text/javascript" src="../../common/jsext/sea-debug.js"></script>

    seajs 的简单配置

    seajs.config({ base: "../sea-modules/", alias: { "jquery": "jquery/jquery/1.10.1/jquery.js" } }) // 加载入口模块 seajs.use("../static/hello/src/main");//入口

    定义模块:

    // 所有模块都通过 define 来定义 define(function(require, exports, module) { // 通过 require 引入依赖 var $ = require('jquery'); var Spinning = require('./spinning'); // 通过 exports 对外提供接口 exports.doSomething = ... // 或者通过 module.exports 提供整个接口 module.exports = ... });

    另外可以使用seajs-text加载html文件或者tpl片段,seajs-css加载css文件

    <script src="path/to/sea.js"></script> <script src="path/to/seajs-text.js"></script> <script> define("main", function(require) { // You can require `.tpl` file directly var tpl = require("./data.tpl") //或者html var html =require("./a.html"); $('.some_class').append(html); }) </script>

    seajs-css

    <script src="path/to/sea.js"></script> <script src="path/to/seajs-css.js"></script> <script> // seajs can load css file after loading css plugin. seajs.use("path/to/some.css"); //很多时候可以使用require的方式 require("path/to/some.css"); </script>

    4.1 ES6时代

    //bar.js function hello(who){ return "hello "+who; } export {hello}; //foo.js import {hello} from "bar"; var n = "zry"; function awe(){ console.log(bar.hello(n).toUpperCase()); } export {awe}; //baz.js import {bar} from "bar"; import {foo} from "foo"; console.log(bar.hello('smt'));//hello smt foo.awe();//HELLO ZRY

    当然现在需要使用babel转成es5,并且要使用打包工具browserify webpack rollup 等才能直接在现在的浏览器上运行。

    参考阅读:

    Javascript模块化编程(一):模块的写法Javascript模块化编程(二):AMD规范 Javascript模块化编程(三):require.js的用法seajs-githubseajs官网seajs-text《你不知到的javascipt》阮一峰-es6入门
    转载请注明原文地址: https://ju.6miu.com/read-1200255.html
    最新回复(0)