美文网首页
模块化开发一 seajs

模块化开发一 seajs

作者: 九泰修行 | 来源:发表于2017-02-16 00:09 被阅读345次

    模块化开发

    随着团队开发的复杂化,我们依赖的代码库会越来越多;
    

    安装

    npm install spm -g
    spm install seajs
    

    可以安装:
    安装bower
    npm install -g bower
    安装seajs
    brwer install seajs
    github:
    http://github.com/seajs/seajs

    也可以下载成一个js文件引入
    <script src="../lib/sea.js"></script>
    <script>
    console.log(seajs.version)
    </script>

    知识

    • 前端这些模块管理的实现是基于AMD规范(异步、管理、加载规范),在最终实现的时候尊重commndjs规范(nodejs就是这个),定义模块时有两种,第一个是只传一个参数就是commndjs规范,传递多个参数的时候,写法尊重moduletransport规范;

    • 通常define只允许我们定义一个模块,当定义多个模块的时候,后面的会覆盖掉前面的;

    seajs文件路径是以sea.js作为出发点的 , 如果是'./'则以自身文件夹为出发点

    使用

    建立一个de.js文件

    seajs.use('de')
    

    在控制面板networks里能看到de.js被加载进来了

    define

    当传递一个参数的时候,参数就是一个模块,参数可以是任意类型;
    

    在de.js中:
    console.log('hello')

    index.html:
    seajs.use('de',function(main){
    })

    控制台输出:hello 字符串

    define传递:
    de.js输入define('hello')

    index.html:
    seajs.use('de',function(main){
    console.log(main)
    })
    控制台输出:hello 字符串

    de.js输入

    define({
        color:'red',
        say:function(){
            return 'hello'
        }
    })
    

    控制台输出一个对象

    • 如果不写在define里就是一个undefined

    我们还可以传递函数,这是一种最复杂的方式,工作中基本是这种方法:

    这个函数自带三个参数:
    require:引用其它模块的工厂方法
    exports:返回的接口对象
    module:模块的module属性集
    
    define(function(require,exports,module){
        return {
            color:'yellow'
        }
    })
    
    • 当传递多个参数时,两个或者三个
      如果传递两个参数的时候,第一个参数表示该模块依赖的模块数组集合,最后一个参数是function;
      如果传递三个参数的时候,第一个表示模块的名称,第二个表示该模块依赖的模块集合,第三个参数就是个function;
    define('main',[],function(require,exports,module){
        return {
            color:'yellow'
        }
    })
    

    模块的依赖

    • 包就是前段说的模块
    • 当传递模块名称的时候,模块的名称就是该名称,当不传递模块的名称的时候,该模块的名称就是该文件的名称,通常我们将模块的名称与文件的名称保持一致

    我们再新建一个header.js文件:

    define(function(){
        return {
            color:'orange'
        }
    })
    

    在main.js中引用:

    define(function(require,exports,module){
        var header = require('./header/header');
        console.log(header)
        return {
            color:'yellow'
        }
    })
    

    index.html的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script src="js/sea.js"></script>
        <script>
            seajs.use('main',function(main){
                console.log(main)
            })
        </script>
    </body>
    </html>
    

    控制台输出两个对象;

    use

    
    seajs.use(['header/header','header/skin/skin'],function(header,skin){
        console.log(header,skin)
    })
    

    第一个参数可以是一个字符串,也可以是一个模块数组,有多少个,在回调函数的参数就有多少个;

    我们可以使用header:

    define(function(require,exports,module){
        var header = require('./header/header');
        document.body.style.background = header.color;
        return {
            color:'yellow'
        }
    })
    
    • require规范:
      1. require不能简写;
      2. require不能被重新定义;
        • 不能赋值 var req = requie;是不可以的
        • 不能定义函数 function require 是不可以的
        • 不能在子函数中的参数中使用require
        • 不能在子函数的作用域内重定义(重复上面三条)
      3. require的参数只能是完整的字符串,拼接也不行require('abc' + 'cde')是不可以的;
    • require的参数值如何定义:
      参数值表示的是文件的路径,相对于sea.js,当然也可以./从自身目录出发

    项目目录:
    - index.html
    - js文件夹
    - sea.js
    - main.js
    - header文件夹
    - header.js
    - skin文件夹
    - skin.js
    skin.js:

    define(function(){
        return 'haha'
    })
    

    在main.js中引用:

    define(function(require,exports,module){
        var header = require('./header/header');
        var skin = require('header/skin/skin')
        console.log(skin)
        document.body.style.background = header.color;
        return {
            color:'yellow'
        }
    })
    

    控制台输出:haha
    require:

    • 可以看到是以sea.js为路径起始点,也就是根目录;
    • 加载js文件,后缀名不写;
      define:
      require,exports,module不能更改

    前面说到定义一个模块的时候最好名字和文件名一样,默认不写模块名;

    如果我们写了不一样的名字会怎么样呢?
    header.js中:

    define('haha',[],function(){
        return {
            color:'orange'
        }
    })
    

    可以看到模块的名字为haha,依赖为空数组,文件名是header.js

    main.js:

    define(['header/header'],function(require,exports,module){
        var a = require('haha');
        var skin = require('header/skin/skin')
        console.log(a,111)
        return {
            color:'yellow'
        }
    })
    

    可以看到控制台可以输出结果;
    所以

    • define的数组参数为依赖的模块路径
    • require为引入的模块名字
    • 如果两者相同,就可以直接var header = require('header/header'),不要后缀名.js

    exports

    • export是保留字,所以使用exports;
    • 表示模块的接口,
      第一种:直接对exports添加属性,如exports.color = 'red';
      第二种:通过module来定义,module.exports.color = 'yellow';
      第三种:通过module来定义,module.exports = {color: 'orange'};
      第四种:通过return来定义,return {color:'green'};

    我们在一个模块中定义接口的时候,只能使用一种,不能混用,后面的会覆盖前面的;

    我们不可以直接对exports赋值新对象

    main.js

    define(function(require,exports,module){
        var a = require('header/header')
        console.log(a)
    })
    
    

    header.js

    define(function(require,exports,module){
        exports.color = 'red'
    })
    

    注意:使用exports接口的header模块,require,exports,module三个参数必须写上;

    第二种方式header.js:

    define(function(require,exports,module){
        module.exports.color = 'red'
    })
    

    第三种方式header.js:

    define(function(require,exports,module){
        module.exports={
            color:'blue'
        }
    })
    

    第四种方式header.js:

    define(function(require,exports,module){
        return {
            color:'white'
        }
    })
    

    module

    我们console.log(module);
    有四个属性:

    1. id 模块名 默认为路径一致 如果id不与uri一样则要分开引用
    2. uri 路径
    3. dependencies 依赖的模块 放在数组里
      deps 依赖的模块 放在对象里
    4. exports是我们返回的接口;

    小案例

    • 项目根目录
      • index.html
      • js文件夹
        • main.js
        • sea.js
        • lib文件夹
          • dom.js
          • event.js
          • string.js

    index.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <button id="btn">猜一猜</button>
        <div id="out"></div>
        <script src="js/sea.js"></script>
        <script>
            seajs.use('main',function(){})
        </script>
    </body>
    </html>
    

    main.js:

    define(function(require,exports,module){
        var Evt = require('lib/event');
        var Dom = require('lib/dom');
        var Str = require('lib/string')
        var msg = 'i don\'t know'
        Evt.on('btn','click',function(){
            Dom.html('out',Str.upper(msg))
        })
    })
    
    

    dom.js

    define(function(){
        var Dom = {
            g: function(id){
                return document.getElementById(id);
            },
            html:function(id,html){
                if(html){
                    this.g(id).innerHTML = html;
                }else{
                    return this.g(id).innerHTML;
                }
            }
        }
        return Dom;
    })
    
    

    event.js

    define(function(require,exports,module){
        var Dom = require('lib/dom')
        var Evt={
            on: function(id,type,fn){
                Dom.g(id)["on"+type] = fn;
            }
        }
        return Evt;
    })
    

    string.js

    define(function(){
        var Str = {
            upper:function(str){
                return str.toUpperCase();
            }
        }
        return Str;
    })
    
    require.async异步调用,跟use方法很像,我们在页面初始化使用use异步加载模块,在模块内部想实现模块的异步加载,就要用require.async方法;

    案例一:
    header.js:

    define(function(require,exports,module){
        return {
            color:'white'
        }
    })
    

    main.js:

    define(function(require,exports,module){
        var header = require('header/header')
        return {
            color: header.color
        }
    })
    
    

    index.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            html,body{
                height:100%;
            }
        </style>
    </head>
    <body>
        <script src="js/sea.js"></script>
        <script>
            seajs.use('main',function(main){
                console.log(main)
            })
        </script>
    </body>
    </html>
    

    就可以得到header的color为white;

    如果采用require.async(第一个参数为字符串也可以是数组,第二个参数是回调函数),和use很像;

    define(function(require,exports,module){
        // var header = require('header/header')
        var header = require.async('header/header',function(header){
            console.log(111,header)
        })
        return {
            color:header.color
        }
    })
    
    • 再来看下面的代码:
    var loadSkin = false;
        if(loadSkin){
            var skin = require('header/skin/shin')
        }else{
            var header = require('header/header')
        }
    
    

    其实两个文件都会加载请求回来,但是skin打印是undefined
    如果换成异步加载:

    var loadSkin = false;
        if(loadSkin){
            var skin = require.async('header/skin/shin')
        }else{
            var header = require.async('header/header')
        }
    

    可以看到不会执行的代码文件不会加载;

    seajs.config({})

    写在index.html seajs.use上面

    seajs.config接收一个对象参数,用来配置一些选项参数的,接收一个对象,里面的属性值,就是我们配置的选项;

    1. alias

    alias:{
        util:'lib/unitl-2.0'
    }
    

    这个可以解决一个问题:lib里面版本库文件,如果在main.js,header.js等等一大堆文件中引用:

    var util = require('lib/util-2.0');
    

    如果一天这个文件升级到了2.1,那么就要去打开这些引用了它的文件去修改,就会造成麻烦,所以alias就是解决这个问题的;
    在alias中把这个文件定义为util,在mainjs,headerjs等文件中要使用它,只需要

    define(function(require,exports,module){
        var util = require('util');
        console.log(util)
    
    })
    
    

    这样如果文件版本升级,只需要更改alias里面的路径即可;

    2. paths

    paths:{
        m:'module/header'
    }
    

    如果我们要引用module/header下面的header.js

    var header = require('module/header/header');
    

    如果按照上面定义好了的路径,以后引用这个文件夹下的文件只需要:

    var header = require('m/header')
    

    3. vars

    vars:{
        hd:'header'
    }
    

    如何使用:

    // var a = require('module/header/skin/skin')
    
    var a = require('module/{hd}/skin/skin')
    

    如果:

    vars:{
        hd:'header/skin'
    }
    

    var a = require('module/{hd}/skin')
    

    通过{}来匹配

    4. map

    map:[
        ['.js','.min.js']
    ]
    

    映射,把所有的js文件做匹配处理;
    如果有文件打包后,文件名可能不同,可以通过这个来处理;

    相关文章

      网友评论

          本文标题:模块化开发一 seajs

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