zoukankan      html  css  js  c++  java
  • js-模块化

    1.什么是模块化:

    将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。

    发展过程:

    (1)无模块化(最早是将所有的js代码写在一个文件里,这样不利于阅读查找)

    script标签引入文件,相互罗列,但是被依赖的放在前面,否则使用就会报错。

    <script src="jquery.js"></script>
    <script src="jquery_scroller.js"></script>
    <script src="main.js"></script>
    <script src="other1.js"></script>
    <script src="other2.js"></script>
    <script src="other3.js"></script>

    即简单的将所有的js文件统统放在一起,但是这些文件的顺序还不能出错,比如jquery需要先引入,才能引入jquery插件,才能在其他的文件中使用jquery。

    缺点:

    • 污染全局作用域(global)
    • 很容易命名冲突
    • 维护成本高
    • 依赖关系不明显
    • 耦合度高(关联性强,不利于后期维护)(什么是耦合?‘高耦合,牵一发而动全身’:‘低耦合,关联性相对低’)

    (2)简单封装:Namespace模式(把一部分数据放在对象里,通过对象.属性操作数据)

         特点:减少了global上的变量的数目,但本质是对象,不安全。

    (3)匿名闭包:IIFE模式(把一些逻辑写到立即执行函数里),这样相对安全。

    (4)引入依赖

    2.为什要模块化

    (1)降低复杂度,降低耦合性,减少他们之间的复杂性。

    (2)部署方便(比如js1模块专门正对轮播图,但这个版块没有轮播图,则这个版块完全没有必要引入)。

    3.模块化的好处

    (1)避免命名冲突(减少命名空间的污染)

    (2)更好的分离,按需加载

    (3)更高的复用性

    (4)高可维护性(方便维护)

    4.页面引入加载script

    但现实是:

    要加载多个script标签,要发起多次请求,依赖模糊,难以维护。

    5.规范

    CommonJS(node根据该规范编写)

    规范:

    (1)每一个文件都可以当做一个模块

    (2)在服务器端:模块的加载是运行时同步(会等待,阻塞)加载的

    (3)在浏览器端:模块需要提前编译打包处理

    语法:

      引入模块:require(xxx)

        第三方模块:xxx为模块名

        自定义模块:xxx为模块文件路径

      暴露模块:

        (1)module.exports=value(exoports本身是一个空对象,module.exports=value是给exports对象添加属性或方法。)

        (2)exports.xxx=value(exports.xxx=value是直接用value新对象来覆盖原来的空对象。)

            module.exports={foo:'bar'};//true

            module.exports.foo='bar';//true

            export={foo:'bar'};//false,相当于重新依赖了exports

        问题:暴露的模块本质是    exports对象

    优点:

    • 解决了依赖、全局变量污染的问题

    缺点:

    • CommonJS用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,CommonJS不适合浏览器端模块加载,更合理的方案是使用异步加载,比如下边AMD规范。

    AMD(专门用于浏览器端的模块化规范,模块的加载是异步的,实现(浏览器端):Require.js)

     语法:

      定义暴露模块:

        //定义没有依赖的模块:

        define(function(){

          return 模块

        })

        //定义有依赖的模块:

        define(['module1','module2'],function(m1,m2){

          return 模块

        })

    区别于CommonJS,AMD规范的被依赖模块是异步加载的,而定义的模块是被当作回调函数来执行的,依赖于require.js模块管理工具库。当然,AMD规范不是采用匿名函数自调用的方式来封装,我们依然可以利用闭包的原理来实现模块的私有成员和公有成员:
    define(['module1', 'module2'], function(m1, m2) {
        let x = 1;
        function add() {
            x += 1;
            return x;
        }
        return { add };
    })

      引入使用模块:

        require(['module1','module2'],function(m1,m2){

          使用 m1/m2

        })

    CMD(专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行,实现(浏览器端):Sea.js

    AMD 推崇依赖前置,CMD 推崇依赖就近。

    CMD集成了CommonJS和AMD的的特点,支持同步和异步加载模块。CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。因此,在CMD中require函数同步加载模块时没有HTTP请求过程。

     基本语法:

      //定义没有依赖的模块:

      define(function(require,exports,module){

        exports.xxx = value

        module.exports = value

      })

      //定义有依赖的模块:

      define(function(require,exports,module){

        //引入依赖模块(同步)

        var module2 = require("./module2")

        //引入依赖模块(异步)

        require.async("./module3",function(m3){

        })

        //暴露模块

        exports.xxx = value

      })

      引入使用模块:

       require(function(require){

        var m1 = require('./module1')

        var m4 = require('./module4')

        m1.show()

        m4.show()

      })

    ES6

    说明:依赖模块需要编译打包处理;

    特点:

    • 模块化规范输出的是一个值的拷贝,ES6模块输出的是值的引用。
    • 模块化规范是运行时加载,ES6模块是编译时输出接口。

    语法:

      (1)导出模块:export xxx

      (2)引入模块:import xxx from "url"

    实现(浏览器端):

      (1)使用Babel将ES6编译为ES5(有些浏览器不兼容ES6)

      (2)使用Browserify编译打包js


    ES6模块化详:

    1.首先页面引用,需要在<script></script>里添加type='module'

    2.导出模块分为默认导出和指定导出

            let name ='wangwu';
            let age=18;
            let module1 =function(){
                console.log(`你好,我是$(name),今年$(age)岁了。`)
            };
            export default module1;//默认导出
            export {name,age,modue1}//指定导出

     两者的区别主要在于引用的时候:

    • 如果是用默认导出export default,接收的时候可以使用任意名字来接收,如下所示,导出的叫module1,被接收的名字叫x:
    import x from 'js/module1.js';
    • 如果要一次导出多个,需要用 { } 包裹,接收的时必须与导出时同名:
    import {name,age,module1} from 'js/module1.js';
    • 如果一个模块既有默认导出,又有指定导出
    export default module1;//默认导出
    export {name,age,module1};//指定导出

        接收时可以使用:

    import x,{name,age,module1} from 'js/module1.js';//默认导出的依然可以随意命名

    3.如果是同级目录,必须添加./

    如果有两个模块里导出的内容是一样的,此时console.log,就会报错

    import x,{name,age,module1} from './module1.js';
    import y,{name,age,module1} from './module2.js';
    console.log(name);//此时module1,module2都导出了name报错
    import x,{name as name1} from './module1.js';
    import y,{name as name2} from './module2.js';
    //as相当于重命名
    console.log(name1);
    console.log(name2);

     4.只有import会只执行代码,不会执行函数

      有一个新的module.js:

    console.log('这是module3');
    function x(){
      console.log('这是module3里面的函数');
    }

       然后在main.js里面直接引用:

    impotr './module3.js';

       可以看到只打印了'这是module3',而函数没有执行。

    5.集体导入

      如果模块里导出的东西太多,又不想引用的时候一个一个的写出来,可以这样:

    import * as x from './module1.js';//这里的*可理解为css里的通配符,意思是所有

       此时打印出x,可以看到

     module1.js里面导出的都在x下了,现在可以用x.age(),x.module1()来调用。


    ES6-Babel-Browserify使用教程

    1.定义package.json文件

    {
      "name":"es6-babel-browserify",
      "version":"1.0.0"   
    }

    2.安装babel-cli,babel-preset-es2015和browserify(cli:command line interface)

    * npm install babel-cli browserify -g (babel全局安装)

    * npm install babel-preset-es2015 --save-dev 

    * preset 预设(将es6转换成es5的所有插件打包)

    3.定义 .babelrc 文件(rc:run control 运行时控制文件,就是运行时要读的文件)

    {
      "presets":["es2015"]  
    }
    ...

     4.编码

    * js/src/module1.js  分别暴露

     参考引用原文:https://www.jianshu.com/p/ae4e566212ff

     参考引用原文:https://www.imooc.com/article/43781?block_id=tuijian_wz

     参考引用原文:https://www.jianshu.com/p/2be0e7956854

  • 相关阅读:
    相关系数的元分析,以及带调节变量的相关系数的元分析(R)
    共有地址网段类别的划分,几个特殊的私有地址,关于子网掩码,网关的小知识 (网络)
    在文件内夹内部建立子文件夹(python)(os)
    晶振, 机器周期,进位 (单片机)
    数码管动态显示,显示从1到9,每一位显示一个数字 (单片机)
    比较R平方的差值,比较两个回归方程的(R)
    react项目控制台报错data.slice.is not function
    useRef源码
    useReducer源码实现
    useContext源码解读
  • 原文地址:https://www.cnblogs.com/czh64/p/11950819.html
Copyright © 2011-2022 走看看