模块化-理解模块化
根目录 ├── index.html # 主页的页面 ├── index.js # 主页需要用到的js代码 │ └── getData() # 是index.js中定义的函数 └── tool.js # 为整个项目提供公共方法 └── doSomething(){ } # 是tool.js中定义的函数
对于如上的代码结构,如何让index.js中的getData去使用tool.js中的doSomething()函数?
- 上面的代码写法,会有什么问题?
- 为什么不能直接让index.js来直接使用tool.js的函数,而要通过index.html来统一管理一下呢?
原因很简单:es5中不支持模块化(不能直接在一个js文件中去引用另一个js文件的方法,必须要通过第三个文件.html来引入)
啥是模块化?
一个js文件可以引入其他的js文件,能使用引入的js文件的中的变量、数据,这种特性就称为模块化。
使用模块化开发可以很好的解决变量、函数名冲突问题,也能灵活的解决文件依赖问题。
模块化的发展
- 以前
es5不支持模块化,让前端人员很为难。为了让支持模块化,我们一般会借用第三方库来实现:
-
- sea.js. SeaJS - A Module Loader for the Web
- require.js. RequireJS
- 现在
-
- es6原生语法也支持模块化(并不表示浏览器也直接支持模块化 --- 需要单独设置一下)
- Nodejs内部也支持模块化(与es6的模块化有些不同之处),具体的语法在后面来介绍。
常见的模块化规范有
- CommonJS 规范(nodejs 默认支持的)
- ES6 模块化规范
- CMD 和 AMD 模块化规范(不再推荐使用)
模块化-体验模块化
演示性的学习,让大家了解几种模块化的写法
- nodejs的模块化
- es6的模块化
- sea.js
- require.js
参考:LABjs、RequireJS、SeaJS 哪个最好用?为什么? - 知乎
nodejs中的模块分类
每个模块都是一个独立的js文件。每个模块都可以完成特定的功能,我们需要时就去引入它们,并调用。不需要时也不需要管它。(理解于浏览器的js中的Math对象)
nodejs模块的分类
- 核心模块
-
- 就是nodejs自带的模块,在安装完nodejs之后,就可以随意使用啦。相当于学习js时使用的Array对象。
- 例:fs, http, querystring, path
- 全部模块的源代码 node/lib at master · nodejs/node · GitHub
- 自定义模块
-
- 程序员自己写的模块。就相当于我们在学习js时的自定义函数。
- 第三方模块
-
- 其他程序员写好的模块。nodejs生态提供了一个专门的工具npm来管理第三方模块,后面我们会专门讲到。
- 相当于别人写好的函数或者库。例如我们前面学习的JQuery库,arttemplate等。
自定义模块-基本介绍
目标
掌握自定义模块的使用背景和步骤
背景
我们对代码的封装是以模块(一个独立的.js文件
)为单位进行的。一般的做法是实现好某一个功能之后,封装成一个模块,然后在其它文件中使用这个模块。
类比于js自定义函数,自定义模块的使用场景是:
- 代码需要在项目重用
- 代码需要提供给他人使用
- 代码虽然不需要重用,但封装成模块有利于优化代码结构,方便后期维护与扩展
步骤
一共有两步:
- 定义模块。就是创建一个js文件, 对外导出我们希望导出的内容。
- 使用模块。在需要使用的地方去导入模块文件。
Node.js 中的 CommonJS 的模块化规范
CommonJS 规范
CommonJS 规范中主要规定了以下 3 项内容:
- 导入其它模块时,统一使用 require() 函数。
- 每个 .js 文件,都是一个独立的模块,模块内的成员都是私有的。
- 在每个 JS 模块中,使用 module.exports 向外共享成员。
图示
根目录 ├── user.js # 定义模块 └── test.js # 引入user.js模块
注意
- module.exports 是固定写法,一般放在文件的最末尾,也只用一次。
- module.exports表示当前模块要暴露给其它模块的功能。
-
- 它可以导出对象,数组,函数等等类型。为了方便组织代码,导出对象的情况比较多。
- 不必要导出所有函数,对象,数组等。那些没有导出的部分就相当于这个模块的内部变量了。在下图中变量1,函数1,数组就是模块内部的数据,在外部无法别访问到。
小结
所谓定义模块,就是新建一个js文件。文件取名时,要注意一下:
- 一般会用模块名给它命名。类比于核心模块,例如,你的模块叫myModule,则这个js文件最好叫myModule.js
- 不要与核心模块的名字重复了。就像我们定义变量不要与核心关键字重名,你自己定义的模块也不要叫fs.js,因为nodejs有一个核心模块就叫fs.js。
- 要记得导出模块
自定义模块-实操
假设在工作中我们自己定义了一些工具方法, 而这些工具方法是可以在其他项目中使用的。此时我们就可以采用自定义模块的方式来处理。
素材
以下是一个对时间进行格式化的函数
const formatDate = (dateTime) => { const date = new Date(dateTime) // 转换成Data(); const y = date.getFullYear() let m = date.getMonth() + 1 m = m < 10 ? '0' + m : m let d = date.getDate() d = d < 10 ? ('0' + d) : d return [y,m,d].join('-') }
这个函数如何才能被复用呢?
我们以此为基础,开始做自定义模块的动作
思路
根目录 ├── tool.js # 把我们要用到的公共方法 封装在这个文件中 └── test.js # 测试tool.js中封装的方法
操作
定义模块
// 方法定义在这里 const formatDate = (dateTime) => { const date = new Date(dateTime) // 转换成Data(); const y = date.getFullYear() let m = date.getMonth() + 1 m = m < 10 ? '0' + m : m let d = date.getDate() d = d < 10 ? ('0' + d) : d return [y,m,d].join('-') } // 通过module.exports来导出模块 module.exports = { formatDate };
记得要导出模块: 在文件尾部,使用module.exports来导出模块。
导入模块
完成了模块定义之后,我们就可以在另一个文件中使用这个模块了。
基本步骤是:
1. 导入模块;格式:const 模块名 = require('./模块路径')
2. 先打出来看看;
当一个模块被成功引入之后,就可以类比使用核心模块的过程一样去使用它们了。
下面是示例代码:
// test.js // 1. 导入模块 // 注意这里使用的是相对路径。可省略.js. const tool = require('./tool.js'); // 在使用之前请先打印出来看看 console.log(tool); // 2. 使用模块中的方法 console.log(tool.formatDate(Date.now()))
注意:
- 使用require语句引入你定义好的模块
- 这里必须使用
相对路径
的格式去引入自定义模块。"./" 也不能省略。
练习
将如下的方法补充到上面封装的tool.js中,并导出使用
//tools.js const relativeTime = (oldTime) => { const t = new Date(oldTime) // Date.now():现在的时间戳(毫秒)