1.
js中级中讲到了模块化演变,后续的演变就是,出现了AMD、CMD、CommonJS等模块化标准,然后前端模块化进入了大爆发时代。
什么是JS模块化
js模块化就是指js代码分成不同的模块,模块内部定义变量作用域只属于模块内部,模块之间变量命名不会相互冲突。各个模块相互独立,而且又可以通过某种方式相互引用协作。
模块化的标准
目前前端流行的几个模块化标准:CommonJs标准(node的方案)、AMD、CMD、ES6模块方案。
未来的趋势肯定是ES6的标准方案会逐渐统一。但是AMD、CMD标准跟CommonJs的标准相差不大,需要我们都研究一下。
模块化的原理:(作用:通过模块来实现变量的作用域隔离,以实现 防止变量的冲突!)
Node.js的强大
Node.js有一个简单的模块加载系统,遵循的是CommonJS的规范。在Node.js中,文件和模块是一一对应的。(每个文件被视为一个独立的模块)。
Node在加载JS文件时,自动给JS文件包装上定义模块的头部和尾部。
// (模块化)思想进阶之路
2.requirejs入门(amd里的,了解)
requirejs的使用:
- requirejs下载
- 把requirejs直接引入到html中
<script src="js/require.js"></script> - 设置当前页面的js入口文件
<script src="js/require.js" data-main="js/main"></script>
data-main属性:指定网页程序的主模块。(当前整个网页的入口代码) - 引用其他模块的文件
ps:
- amd的东西很少,就做了两件事:①模块怎么定义;②模块怎么使用。
- amd是异步的模块规范
- 相关信息可以去GitHub上amd查找
示例代码:
1. learn_2_myfirstdemo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>requirejs实现amd标准的应用</title>
</head>
<body>
<div id="box"></div>
<script src="lib/require.js" data-main="learn_2_index.js"></script>
</body>
</html>
2. learn_2_index.js
// 注意!要进行require的config配置路径映射。
require.config({
paths: {
jquery: 'lib/jquery-3.4.1', // 注意.js这个后缀不要加上
show: 'learn_2_show' // 配置自己定义模块的路径
}
});
// define定义一个模块 (ps:若不用require.config进行路径配置,那么在[]里的对应模块就要写上路径,比如如果不在require.config中对show进行配置,那么[]里的show就要写成“"./show.js"”)
define(['jquery', 'show'], function($, show) { // function里的参数是对应模块的返回
'use strict';
$("#box").html("<h1>第一个requirejs应用</h1>");
show.do();
});
// []:依赖的模块名(注意:小写)
// 由于在jquery-3.4.1.js代码中有:
// if ( typeof define === "function" && define.amd ) {
// define( "jquery", [], function() {
// return jQuery;
// } );
// }
// 其返回一个jQuery对象,故用$来接收它。
// 自定义模块learn_2_show.js返回一个对象,此处用show来接收
3. learn_2_show.js
// 一个自己定义的模块
define([
'jquery'
], function ($) {
'use strict';
// 对外输出一个东西(此处为返回一个对象)
return {
do: function () {
console.log("我是show模块");
$(document.body).append("<div>我是动态生成的!</div>");
}
}
});
运行演示:
3.CMD与Sea.js
略
4.node
1.引入自定义模块
1.npmjs.com 网站有很多node的第三方模块。
如 string-width :Get the visual width of a string - the number of columns required to display it
使用:
- 安装 npm install string-width
会在当前工作目录生成文件夹 node_modules,下载的就在里面;
同时在package.json(用 npm init生成的,用于管理本项目的package的配置文件)里会自动添加:"dependencies": {
"string-width": "^4.2.0"
}
- 使用
示例代码:
// 4:自定义模块
const stringw = require("string-width");
var num = stringw("lili");
console.log(num); // 4
2.自己写的模块
示例代码:
自定义math模块:
// 一个文件就是一个模块
let math = {
add: function(a, b){
return a + b;
}
}
module.exports = math; // 导出
引入自定义math模块:
// console.log(module);
// 引入 learn_4_math.js文件对应的模块。
// 引入learn_4_math模块,t就指向引入的模块
let t = require('./learn_4_math'); // ! let和var的区别自己查
// 调用learn_4_math模块的add方法
console.log(t.add(9, 10)); // 运行结果 控制台输出 19
ps:module有一个paths的属性,如下图,然后node找的路径从(图里)上依次到下。(实际是从本目录找,到上级目录,一直到根目录)
示例:
自定义是搜索最慢的,当然第二次就在缓存里了。
2.引入内置模块
内置模块有很多,比如:断言模块、缓冲器模块、等等(详见官网nodejs.cn/api/)),注意其中的控制台(console)模块,可以直接用。
ps:文件模块中,又分为3类模块。这三类文件模块以后缀来区分,Node.js会根据后缀来决定加载方法。
- .js 通过fs模块同步读取js文件进行编译执行。
- .node 通过c/c++进行编写的Addon。通过diopen方法进行加载。
- .json 读取文件,调用JSON.parse解析加载。
示例代码:
// 1.引入内置的模块
const path = require('path') // const:定义一个常量,如果是简单类型,那么值不能修改;如果是引用类型,则变量指向的内存地址不变。
var t = path.join(__dirname, __filename); // path的join方法作用:把多个路径粘结在一起,并规范化生成路径。(详请查阅文档)
console.log(t); // C:\Users\lisa\Documents\My\Learn_CodeTych\Vscode\node2_laoma\C:\Users\lisa\Documents\My\Learn_CodeTych\Vscode\node2_laoma\learn_5_nodemodule_require.js
3.引入文件模块
示例代码:
// 2. 引入文件模块 (相对路径和绝对路径都可以)
const math = require("./learn_4_math.js"); // ps:文件后缀可以加,也可以不加,但推荐 加上后缀,这样效率高。(因为当不加后缀时,执行时引擎会尝试加js后缀、json后缀或.node(c/c++进行编写的Addon,通过diopen方法进行加载)后缀等,若没有找到对应的,就报错。
console.log(math.add(9, 9)); // 18
// 引入绝对路径
const math2 = require("C:/Users/lisa/Documents/My/Learn_CodeTych/Vscode/node2_laoma/learn_4_math.js");
console.log(math2.add(1, 4)); // 5
4.引入 文件夹模块(尽量少用!)
示例代码:
learn_5_nodemodule_require.js
// 3.引入 文件夹模块 (尽量少用!性能不好)
// step1:到根目录的package.json文件中去找main的配置节点。
// step0:创建package.json文件: (在该package.json中,我们的入口文件名叫index.js;则后续寻找时就用require中给的路径加这个文件名(index.js)来找。)
// 用npm init自动初始化一个配置文件
//(初始化过程中的相关配置按自己需要写:entry point 指入口文件;License(协议)写MIT)
// 创建结束后就会生成一个叫package.json的文件
// 或者直接用命令npm init -y 默认生成
// ps:如果内部未配置好main,具体还有别的找法,详查(略)。(要用package就写好,别给自己找麻烦)
const m = require('./'); // 因为index.js和他在同一个目录,故直接写./
m.show(); // index.js show!
const n = require("./learn_5"); // 此时我们在当前路径下的文件夹中创建了一个index.js,则此时的路径为./learn_5
n.myshow(); // learn_5: myshow
package.json
{
"name": "node2_laoma",
"version": "1.0.0",
"description": "learn_node",
"main": "index.js",
"directories": {
"lib": "lib"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT"
}
当前目录下的index.js
// module.exports 和 exports是一样的;两个不要混用
exports.show = function(){
console.log("index.js show!");
};
// 对外输出的是exports这个对象。
当前目录下的文件夹learn_5下的index.js
exports.myshow = function(){
console.log("learn_5: myshow");
};