美文网首页
javascript如何做模块化

javascript如何做模块化

作者: _贺瑞丰 | 来源:发表于2018-06-23 14:41 被阅读4次

0.模块化是什么

将实现某功能的部分代码 单独隔离成一个模块,包括了变量(数据)与方法。

1.模块化的目的

  • 更好的复用
  • 方便维护

2.常见方式

  • level 1:函数块层级
    将意大利面条代码用函数包裹,将一个大程序分解成若干个函数块
  • level 2 :对象+函数调用
    将意大利面条代码根据实现的功能,做对象化,一个大程序分解成 对象的定义与对象的调用
  • level 3 :对象抽象成类 + 实例化 +调用
    将对象进一步抽象成类,然后在需要的时候实例化出对象,然后调用方法
  • level 4 :上一步的类继续抽象+引入继承

1.1 组件化开发如何封装

封装要考虑JS组件粒度问题,全局变量,引入依赖模块

1.2 如何加载JS资源

组件之间的依赖关系与JS资源的加载速度
全局命名污染

2 . 封装

封装解决了分块问题和命名空间问题
实现途径有:

  • 使用对象封装,并暴露给WINDOW对象
var MYAPP = { foo: function(){}, bar: function(){}}
MYAPP.foo();
window.MYAPP =MYAPP 

问题是:还是在window对象上,并且不安全

  • 立即实行函数:私有化,命名空间问题,更安全
var Module = (function($){
    var _private = "safe now";
    var foo = function(){ console.log(_private)}
    return { foo: foo}
})(jQuery)//引入依赖
Module.foo();
Module._private; // undefined

3.加载

3.1 密集的<script>:难维护,依赖关系呢?HTTP请求多了

所以我们需要的解决的问题是:
1.别出现这么复杂的JS引入
2.要直观的了解依赖关系

  1. 减少HTTP请求数量
    4.支持并行加载OR动态加载
 script(src="zepto.js")
    script(src="jhash.js")
    script(src="fastClick.js")
    script(src="iScroll.js")
    script(src="underscore.js")
    script(src="handlebar.js")
    script(src="datacenter.js")
    script(src="deferred.js")
    script(src="util/wxbridge.js")
    script(src="util/login.js")
    script(src="util/base.js")
    script(src="util/city.js")
    script(src="util/date.js")
    script(src="util/cookie.js")
    script(src="app.js")

3.2 LABjs :基于文件的依赖管理

动态并行加载+执行顺序控制

script(src="LAB.js" async)
$LAB
.script( [ "script1.js", "script2.js", "script3.js"] )
.wait(function(){ // wait for all scripts to execute first
    script1Func();
    script2Func();
    script3Func();
});

3.3 YUI3 Loader

提供了中介沙箱Y,封装后全部导入到Y中,使用时直接调用Y

// YUI - 编写模块
YUI.add('dom', function(Y) {
  Y.DOM = { ... }
})

// YUI - 使用模块
YUI().use('dom', function(Y) {
  Y.DOM.doSomeThing();
  // use some methods DOM attach to Y
})
// hello.js
YUI.add('hello', function(Y){
    Y.sayHello = function(msg){
        Y.DOM.set(el, 'innerHTML', 'Hello!');
    }
},'3.0.0',{
    requires:['dom']
})
// main.js
YUI().use('hello', function(Y){
    Y.sayHello("hey yui loader");
})

Y 其实是一个强沙箱
所有依赖模块通过 attach 的方式被注入沙盒
attach:在当前 YUI 实例上执行模块的初始化代码,使得模块在当前实例上可用

// Sandbox Implementation
function Sandbox() {
    // ...
    // initialize the required modules
    for (i = 0; i < modules.length; i += 1) {
        Sandbox.modules[modules[i]](this);
    }
    // ...
}

script还是多,但是解决了顺序问题,并且基于模块来管理

script(src="/path/to/yui-min.js")       // YUI seed
script(src="/path/to/my/module1.js")    // add('module1')
script(src="/path/to/my/module2.js")    // add('module2')
script(src="/path/to/my/module3.js")    // add('module3')

YUI().use('module1', 'module2', 'module3', function(Y) {
    // you can use all this module now
});

请求过多的问题可以在服务器端的方案解决

4.CommonJS

通过module.exports导出属性和方法
通过其他模块中require来使用
有同步/阻塞加载的问题,在浏览器端弊端很大,服务器端速度快。

// timeout.js
var EXE_TIME = 2;

(function(second){
    var start = +new Date();
    while(start + second*1000 > new Date()){}
})(EXE_TIME)

console.log("2000ms executed")
// main.js
require('./timeout');   // sync load,不可能异步
console.log('done!');

5. AMD VS CMD

AMD代表requireJS
CMD代表seaJS

//CommonJS Syntax
var Employee = require("types/Employee");

function Programmer (){
    //do something
}

Programmer.prototype = new Employee();

//如果 require call 是异步的,那么肯定 error
//因为在执行这句前 Employee 模块根本来不及加载进来

Function Wrapping

//AMD Wrapper
define(
    ["types/Employee"],  //依赖
    function(Employee){  //这个回调会在所有依赖都被加载后才执行
        function Programmer(){
            //do something
        };

        Programmer.prototype = new Employee();
        return Programmer;  //return Constructor
    }
)
语法糖
define(function (require) {
    var dependency1 = require('dependency1'),
        dependency2 = require('dependency2');

    return function () {};
});
// parse out require...
define(
    ['require', 'dependency1', 'dependency2'],
function (require) {
    var dependency1 = require('dependency1'),
        dependency2 = require('dependency2');

    return function () {};
});

相关文章

网友评论

      本文标题:javascript如何做模块化

      本文链接:https://www.haomeiwen.com/subject/vjgryftx.html