• JavaScript模块化功能使用总结


    模块化介绍

    将 JavaScript 程序拆分为可按需导入的单独模块的机制,当然这是官方的解释,我写博客一般不会使用官方的解释,所以用比较通俗易懂的话来讲就是尽可能的将每一个功能点都进行拆分,尽量的每一个模块都是代表一个独立的功能,这样不管是后期的功能组装还是相互引用或者是功能的维护都是有很大的好处的,也是非常具有意义的,那么今天讲的就是如何将代码模块化,模块化需要注意的一些点是什么!

    准备工作

    开始之前我们需要知道的,浏览器开始的时候本身是不支持模块化操作的,也就是说我们所有的模块化操作都是基于nodejs支持的,或者是一些特殊的写法,不过值得说的是,最近的一些浏览器已经开始逐渐支持最新的模块化的操作和写法,今天我们主要的一些操作都是基于nodejs的,当然关于浏览器本身的一些写法我们也会说一下,毕竟不是什么很难的事情,大概了解就可以了!

    注意事项

    • 下面的内容中使用的文件后缀存在的有js和mjs,这个根据自己的浏览器支持能力进行使用
    • 苹果自带的一些文件查看器,会将mjs的后缀默认添加一个js,也就说我们起名字的时候是mjs,但是因为苹果不认识,导致最后我们使用的还是js,那么这个时候我们需要将苹果的默认不看后缀的功能关闭即可

    html中基本使用

    • moduT.mjs
    /**
      * @Description: 测试html中使用模块
      * @author:clearlove
      * @param name
      * @return name
      * @createTime: 2022-07-01 17:17:25
      */
    let name = 'jim'
    export {
    	name,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • index.html
    <script type="module">
    		import {
    			name
    		} from '../js/moduT.mjs'
    		console.log(name)
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    添加关键字module之后可以直接使用export和import进行配合使用js内部的内容

    Module

    注意的点
    • 使用type='module’的时候,不需要添加defer属性,因为这种类型本身就是延迟加载的
    • 使用type='module’的时候,是具有一定的块级作作用域的,也就是我们无法全局使用它们,只可以在script内部使用
    • type='module’默认是严格模式,这个需要注意

    导出方式-〉默认导出

    导出一个匿名函数:moduleDefault.mjs
    /**
      * @Description: 默认导出一个匿名函数
      * @author:clearlove
      * @param function
      * @return console
      * @createTime: 2022-07-01 17:31:07
      */
    export default function(){
    	console.log('this is defaultFunction')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    运行该匿名函数
    /**
      * @Description: 测试使用导出模块
      * @author:clearlove
      * @param function
      * @return f
      * @createTime: 2022-07-01 17:30:44
      */
    import f from  './moduleDefault.mjs'
    f()
    //this is defaultFunction
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    导出一个非匿名函数
    let f = ()=>{
    	console.log('this is not anonymous function')
    }
    export default f
    
    • 1
    • 2
    • 3
    • 4
    运行该模块函数
    import f from  './moduleDefault.mjs'
    f()
    //this is not anonymous function
    
    • 1
    • 2
    • 3
    注意事项
    • 默认导出,不加大括号,每次只可以导出一个默认项

    • 因为是默认导出,所以可以直接使用任何变量名字接收参数

    • //导出name
      let name = 'kim'
      export default name
      //接收otherName
      import otherName from './moduleDefault.js'
      console.log(otherName)
      // kim
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    模块处理-〉非默认

    基本用法
    tools.mjs
    /**
     * @Description: 非默认模块基本用法
     * @author:clearlove
     * @param name age height f
     * @return 
     * @createTime: 2022-07-01 17:46:36
     */
    let name, age, addr, height
    name = 'jim'
    age = 20
    addr = 'ch'
    height = '180cm'
    let f = () => {
    	console.log('this is function')
    }
    export {
    	name,
    	age,
    	addr,
    	height,
    	f
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    use.js
    /**
     * @Description: 测试使用导出模块
     * @author:clearlove
     * @param function
     * @return f
     * @createTime: 2022-07-01 17:30:44
     */
    import {
    	name,
    	age,
    	height,
    	f
    } from './tool.mjs'
    console.log(name) //jim
    console.log(age) //20
    console.log(height) //180cm
    f() //this is function
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    避免命名冲突->重命名导入与导出
    导出使用别名
    /**
     * @Description: 非默认模块基本用法 -- 导出使用别名
     * @author:clearlove
     * @param 
     * @return 
     * @createTime: 2022-07-01 17:46:36
     */
    let f1 = () => {
    	console.log('this is addition')
    }
    let f2 = () => {
    	console.log('this is subtraction')
    }
    let f3 = () => {
    	console.log('this is multiplication')
    }
    let f4 = () => {
    	console.log('this is division')
    }
    
    export {
    	f1 as addition, f2 as subtraction, f3 as multiplication, f4 as division
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    导入使用
    /**
     * @Description: 测试使用导出模块
     * @author:clearlove
     * @param function
     * @return f
     * @createTime: 2022-07-01 17:30:44
     */
    import {
    	addition,
    	subtraction,
    	multiplication,
    	division
    } from './tool.js'
    
    addition() //this is addition
    subtraction() //this is subtraction
    multiplication() //this is multiplication
    division() //this is division
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    反之亦然

    let f1 = () => {
    	console.log('this is addition')
    }
    export {
    	f1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    import {
    	f1 as addition
    } from './tool.js'
    addition() //this is addition
    
    • 1
    • 2
    • 3
    • 4
    避免不同文件相同函数名字-> 创建模块对象

    当然一般情况下,如果不是一个人在写模块的话,这种现象出现的概率还是很大的,一个人写的时候可以注意一点,根据文件名字进行不同的区分,如果在使用的时候出现了此类的问题,可以按照上面的相同的方式解决,导出的时候进行重命名即可!当然既然写了,就是希望有一个更好的方式解决这问题,我们可以创建一个模块对象出来,代码如下:

    • objModuleOne.js
    /**
      * @Description: 创建模块对象功能测试One
      * @author:clearlove
      * @param 
      * @return 
      * @createTime: 2022-07-01 18:14:31
      */
    let drawCircle = () => {
    	console.log('this is OneModulesDrawSquare')
    }
    let drawSquare = () => {
    	console.log('this is OneModulesDrawSquare')
    }
    
    export {
    	drawCircle,
    	drawSquare
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • objModuleTwo.js
    /**
     * @Description: 创建模块对象功能测试Two
     * @author:clearlove
     * @param 
     * @return 
     * @createTime: 2022-07-01 18:14:31
     */
    let drawCircle = () => {
    	console.log('this is TwoModulesDrawSquare')
    }
    let drawSquare = () => {
    	console.log('this is TwoModulesDrawSquare')
    }
    
    export {
    	drawCircle,
    	drawSquare
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    使用模块对象化
    /**
     * @Description: 测试使用导出模块
     * @author:clearlove
     * @param function
     * @return f
     * @createTime: 2022-07-01 17:30:44
     */
    import * as oneModule from './objModuleOne.js'
    import * as twoModule from './objModuleTwo.js'
    oneModule.drawCircle() //this is OneModulesDrawSquare
    oneModule.drawSquare() //this is OneModulesDrawSquare
    twoModule.drawCircle() //this is TwoModulesDrawSquare
    twoModule.drawSquare() //this is TwoModulesDrawSquare
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这样做的好处就是我们可以很清楚的知道我们需要调用的函数,也不需要关心是不是重命名了,因为我们被挂载到不同的模块对象上,这样是根据不同的模块对象进行调用的,我们也是默认使用了所有的内部导出的功能函数,可以直接随意使用我们需要的函数

    类的导出

    /**
     * @Description: 测试模块类
     * @author:clearlove
     * @param 
     * @return 
     * @createTime: 2022-07-01 18:27:09
     */
    class Animal {
    	constructor(name) {
    		this.name = name
    	}
    	eat() {
    		console.log(`${this.name}吃东西`)
    	}
    }
    export {
    Animal
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    /**
     * @Description: 测试使用导出模块
     * @author:clearlove
     * @param function
     * @return f
     * @createTime: 2022-07-01 17:30:44
     */
    
    import {
    	Animal
    } from '../js/classTest.js'
    
    let dog = new Animal('狗')
    dog.eat() //狗吃东西
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    类的模块化其实和函数变量都差不多,只是使用的时候我们需要进行一个实例化的过程,包括里面的构造器或者是一些类的继承都是需要注意的,这个我在我别的文章里面写过了,包括类的继承和一些注意事项,感兴趣的可以自行查找。

    模块化合并操作

    在进行合并操作之前的话,需要说明的一个点,合并的操作需要使用目录结构进行配合使用的,大概的一个目录结构如下,当然理乱上只是为了更加的清晰一点。

    modules/tools.js
    
    • 1
    tools/
    
    • 1
    addition.js
    
    • 1
    division.js
    
    • 1
    subtraction.js
    
    • 1
    • addition.js
    let addition = () => {
    	console.log('this is addition')
    }
    
    export {
    	addition
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • division.js
    let division = () => {
    	console.log('this is division')
    }
    
    export {
    	division
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • subtraction.js
    let subtraction = () => {
    	console.log('this is subtraction')
    }
    
    export {
    	subtraction
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    tools.js 汇总该导出
    export {
    	addition
    } from '/Users/leimingwei/Desktop/LeiMingWei/zxGs/aliyun/modulesShow/src/modules/tools/addition.js'
    export {
    	division
    } from '/Users/leimingwei/Desktop/LeiMingWei/zxGs/aliyun/modulesShow/src/modules/tools/division.js'
    export {
    	subtraction
    } from '/Users/leimingwei/Desktop/LeiMingWei/zxGs/aliyun/modulesShow/src/modules/tools/subtraction.js'
    //这里的路径需要进行将module的路径完全展示出来,否则不太好直接引入到文件内容,如果直接使用下面的方式一的话,是不需要该文件的,但是如果使用的是方式二的话,是需要引入该文件的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    使用方式一 : 正常引入
    import {
    	addition
    } from '../modules/tools/addition.js'
    import {
    	division
    } from '../modules/tools/division.js'
    import {
    	subtraction
    } from '../modules/tools/subtraction.js'
    
    addition() //this is addition
    division() //this is division
    subtraction() //this is subtraction
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    使用方式二: 合并引入
    import {
    	addition,
    	division,
    	subtraction
    } from '../modules/tools.js'
    
    addition() //this is addition
    division() //this is division
    subtraction() //this is subtraction
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    动态加载模块

    动态加载模块其实和导出部分关系不大, 只是我们使用的时候,使用的是模块化本身自带的一些功能,模块化允许我们import当作一个函数使用,返回一个promise,这样我们可以直接进行异步或者一些动作上的操作

    let drawCrl = () => {
    	console.log("start drawCrl")
    }
    export {
    	drawCrl
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    使用html进行演示
    DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>title>
    	head>
    	<body>
    		<button id="crl">点击开始画圆形button>
    	body>
    	<script type="module">
    		let btn = document.getElementById('crl')
    		btn.addEventListener('click', () => {
    			import('../js/dynamicLoad.js').then(s => {
    				s.drawCrl()
    			})
    		})
    	script>
    html>
    //start drawCrl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    使用js进行演示
    /**
     * @Description: 测试使用动态导出模块
     * @author:clearlove
     * @param function
     * @return f
     * @createTime: 2022-07-01 17:30:44
     */
    import('./dynamicLoad.js').then((c) => {
    	console.log(c)
    	c.drawCrl()
    })
    //start drawCrl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    写到最后

    文章至此已经将一些最基础的模块化的使用总结了,那么还是老话,有问题随时联系和留言,我最近很少更新一下项目中的问题,都是一些总结性质的,不是因为项目中没有问题,只是很多的问题不太好描述,同时也不太好说明这个问题的一些前因后果,甚至文章名字都不太好起,所以,有问题的话,一般都是记录下来,不太会占一篇文章来说明,我始终认为一篇好的文章不是教会你解决一个特定的问题,而是更好的扩展你的知识面和总结性质的知识,这样后面遇到的问题的时候自主解决的能力才会得到提高,仅此而已!

  • 相关阅读:
    魔众文库系统 v3.5.0 预览页数调整,批量操作命令,多处优化
    Collction的List方法,list特有方法,遍历方式,迭代器选择
    全景环视前装市场“变天”,这家中国本土供应商首次跻身份额第一
    Spring-手写模拟Spring底层原理
    foreach并行化%dopar%
    LeetCode-946-验证栈序列
    Kakfa客户端SSL访问kafka
    Airtest1.2.7新增断言API介绍
    wx:for-item wx:for-index wx:for-key
    如果你是一个 Java 面试官,你会问哪些问题?
  • 原文地址:https://blog.csdn.net/qq_41485414/article/details/126183402