目录
一、Node简介
- Node.js是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境。
- Node.js主要用于编写像Web服务器一样的网络应用
- 官网地址:Node.js
- 中文官网:Node.js 中文网
1、前端与后台
- 前端:页面(渲染)
- 后端:提供服务
2、学习Node的目的
- 学习Node.js是为了解前后端交互流程
- 同时为后面学习前端框架做准备
- 前端有很多业务不能解决,需要使用Node.js处理
3、Node的特点
- 单线程
- 非阻塞I/O
- 事件驱动
4、Node适合的场景
-
web服务器
-
聊天室
-
不善于计算、善于并发I/O
二、Node安装
1、下载与安装
下载地址:Download | Node.js
2、常见cmd操作
打开命令行:
1.windows +R 输入cmd
2.任意文件资源管理器中,地址栏输入:cmd
...
3、常见的dos命令:
常见的dos命令:
1)cls 清屏
2)dir 查看目录
3)cd 切换到指定的目录
4)md 创建一个新的文件夹
5)rd 删除文件夹(只能删除空文件)
6)rm 删除文件
目的:为了cmd中使用node命令
三、Node运行与顶层对象
1、Node的运行
在cmd工具中,使用命令
node 文件名
eg:
node index.js
2、顶层对象
在浏览器 JavaScript 中,通常 window是顶层对象,而 Node.js 中的顶层对象是 global
globalThis
eg:
console.log(this);//{}
console.log(global);
console.log(globalThis);//顶级对象
3.全局变量
Node平台内置了例如:__filename
和 __dirname
等全局变量 setInterval() setTimeout()等方法
eg:
//绝对路径
console.log(__dirname);//E:\郑州20230816\day07\code
console.log(__filename);//E:\郑州20230816\day07\code\1.全局变量.js
四、模块系统
在Node.js中,一个js文件就称之为一个模块(Module)。
1.模块概述
在进行项目分析或者编码时,先把项目进行拆分,拆分成很多的类,对象,很多的函数等等。能够提高代码的复用性。这些被拆分出来的类型,对象,函数就是模块。就像一辆汽车是由很多的零部件组成,每个零部件就是一个小模块,而由很多零件组成的发动机之于一辆汽车可以认为是一个大模块;或者说,一台计算机,由主板,cpu,内存,硬盘,显示器,键盘等大模块组成。而一个内存或者cpu又分别由很多的小模块组成。以模块为单位管理代码,会更加独立,调试方便,维护也很方便。
简述优势
将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来
2.模块的分类
在Node中,模块分为两类:一类是Node提供的模块,称为核心模块;另一类是用户编写的模块,称为文件模块(自定义模块、第三方模块)。
2.1 内置模块/核心模块
内置模块 NodeJS中自带的模块,可以直接使用
- require("模块名")
- fs/url/querystring/qs/path/http....
例如:url querystring fs ...
eg:
//url模块 处理url
let myUrl="http://192.168.1.1:3000/admin/login?username=jack&pwd=2342#main";
//协议
//主机名
//端口
//路径
//参数
// const url=require("url");
// // console.log(url);
// let newUrl=url.parse(myUrl)
// // console.log(newUrl);
// let {host,port,protocol,query,pathname} =newUrl;
// console.log(protocol);//协议
// console.log(pathname);
// console.log(port);
// console.log(host);
// console.log(query);
// let mmUrl=new URL(myUrl)
// console.log(mmUrl);
const qs=require('querystring');
// console.log(qs);
let str="username=jack&pwd=2342";// --> 对象格式
let rst=qs.parse(str)
// console.log(rst);
let queryObj={
id:1,
username:"admin",
pwd:1123234
}
let ss=qs.stringify(queryObj)
console.log(ss);
2.2 文件模块
文件模块常见的有:自定义模块、第三方模块
自定义模块:
eg:
let fn = function () {
console.log('hello world');
}
let fnx = function () {
console.log('running........');
}
let arr = ['hello', 'yes', 'hi'];
let obj = {
no: "1002",
title: "鞋子",
price: 119
}
//批量导出
module.exports = {
fn: fn, fnx, arr, obj
}
2.2.1 ES6的模块化 (ESM)
1、原生支持模块化了
ES6中新增的模块化,即从ES6开始,原生js支持模块化了,现在很多浏览器也支持模块化了。
2、模块化的两个概念
1)、导出(export关键字):导出就是对外开放的,可以导出变量,常量,函数,对象等等。使用export关键字。放在export关键字后面的(即对外导出的)变量,常量,函数和对象,在其它js文件中可以使用,否则,其它js文件中是不能使用的。即只能内部使用的。
在用export导出时,可以导出多个
2)、导入(import):导入就是把其它js文件引入到当前js文件里。使用关键字import。
3)、在html文件中引入index.js(注意: type="module")注意:js中使用了模块化的关键字import,在引入时,script标签的type属性的值必须写成module。
即:<script type="module" src="js/index.js"></script>
4)export default和export 有什么区别:
- export与export default均可用于导出常量、函数、文件、模块等
- 在一个文件或模块中,export可以有多个,export default仅有一个,而且export default在导出是不需要变量名,相当于匿名的。
- 通过export方式导出,在导入时要加{ },export default则不需要。
3.使用export示范
-
单个导出
-
export.名称=值
-
let obj={ id:111, name:"李强", age:18 } //1.单个导出 export let age=20; export let name="狗蛋" export let addr="门口狗窝"
-
-
批量导出
-
export { 值,....}
-
import {age} from "./person.js" export let fn=function(){ console.log('hello world'); } let fx=function(){ console.log('this...'); } let obj={ id:111, msg:"ok" } export { fx,obj }
-
-
默认导出
-
export default {}
-
//默认导出 // export default { // id: 1, // msg: 'ok', // fn: function () { // console.log('哈哈哈'); // }, // fnx() { // console.log("hello world"); // } // } let a = 10; let b = 'hello world'; let fn = function () { console.log('run.........'); } let arr = [10, 20, 304, 890] export default { ax: a, b: b, fn: fn, arr: arr }
-
导入import:
// console.log(obj);//不能直接访问其它模块的内容
//导入其它模块的内容
//1.导入单个导出
import { age } from "./person.js";
// import {age} from "./person";//error 需要完整的后缀
//2.导入批量导出的内容
import { m1 as mm, m2 } from "./strudent.js"
//3.
import {fn,fx,obj} from "./emplyee.js";
//4.导入默认导出的模块
import xx from "./man.js"
// console.log(age);
// console.log(obj);//error person.js没有导出obj
// console.log(m1);
// console.log(m2);
// fn()
// fx();
// console.log(obj);
console.log(mm);
// console.log(m1);//已改名,不可以使用
// console.log(xx);
// console.log(xx.id);
// console.log(xx.msg);
// xx.fn()
2.2.2 CommonJS的模块化 (CJS)
Node.js是commonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:module、exports、require、global。实际使用时,用module.exports定义当前模块对外输出的接口(不推荐直接用exports),用require加载模块
1、根据CommonJS规范:
- 一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为
global
对象的属性。
-
输出模块变量的最好方法是使用
module.exports
对象。 -
加载模块使用
require
方法,该方法读取一个文件并执行,返回文件内部的module.exports
对象
仔细看上面的代码,您会注意到 require
是同步的。模块系统需要同步读取模块文件内容,并编译执行以得到模块接口。
然而, 这在浏览器端问题多多。
浏览器端,加载 JavaScript 最佳、最容易的方式是在 document
中插入<script>
标签。但脚本标签天生异步,传统 CommonJS 模块在浏览器环境中无法正常加载。
解决思路之一是,开发一个服务器端组件,对模块代码作静态分析,将模块与它的依赖列表一起返回给浏览器端。 这很好使,但需要服务器安装额外的组件,并因此要调整一系列底层架构。
2、使用exports、module.exports
eg:单个导出
// let name='张三';
// let age=20;
// let addr="中州大道";
//单个导出
exports.name = '张三';
exports.age = 20;
exports.addr = "中州大道";
let arr=[10,100,300];
require:
eg:批量导出
let fn = function () {
console.log('hello world');
}
let fnx = function () {
console.log('running........');
}
let arr = ['hello', 'yes', 'hi'];
let obj = {
no: "1002",
title: "鞋子",
price: 119
}
//批量导出
module.exports = {
fn: fn, fnx, arr, obj
}
eg:导入
//入口文件
//导入
// const xx=require("./user.js");// { name: '张三', age: 20, addr: '中州大道' }
// console.log(xx);
// const { age, addr } = require("./user.js");
// const { age, addr ,arr} = require("./user");//可以省略后缀
// // console.log(age, addr);
// console.log(arr);//undefined
// const rst=require("./student");
// console.log(rst);
// console.log(rst.xx.arr);
// let rst=require("./room")
// console.log(rst);
// let {obj,arr} =require("./room");
// console.log(obj,arr);
const xx=require("./classroom");
console.log(xx);
最后通过node
来执行模块。
2.3 模块加载机制和Commonjs简述
-
加载核心模块,如:fs、path等,其实在node运行的时候,已经放到内存中了
-
加上对应文件后缀,优先级为:test.js > test.json > test.node
-
搜索路径,如果有指定路径则按照路径去找,如:require(‘./test’) 则在当前目录寻找,如果没有指定路径,则从当前目录下往上去找 node_modules文件夹,然后从文件夹里去遍历寻找对应模块名,如果找不到则到上一层node_modules去找,直到最顶层目录
-
首次会加载比较慢,后面node.js 会将缓存相关信息到内存避免二次查询
2.4 新特性
在node的新版本中,支持使用[node:module API] 即可以使用node:前缀
来标识核心模块。
这种方式导入包,它会绕过所需的缓存。
区别:
-
直接使用
require('fs')
,需要等node.js将所有核心模块加载完成后才可以使用,这个可以通过module.builtinModules去判断是否加载完成 -
使用
require('node:fs')
,则不需要等待,可以直接调用内置模块,但是却无法使用缓存
总结:如果是对启动速度有要求的功能,建议使用require('node:fs')
模式,其他正常调用即可
2.5 CommonJs和ES6模块化的区别
-
CommonJs模块的require()是同步加载模块,ES6模块的import命令是异步加载模块
-
CommonJs模块是运行时加载,ES6模块是编译时加载或静态加载
-
CommonJs模块加载有缓存,ES6模块加载没有缓存
-
CommonJs模块输出的是一个值的复制,ES6模块输出的是值的只读引用
-
CommonJs加载的是整个模块,即将所有的方法都加载进来,ES6可以单独加载其中的某个方法
-
CommonJs模块中this指向当前模块,ES6中指向undefined
2.6. 模块化的解决方案
以上模块化存在的问题:
不管是以上哪种方式(函数,对象,立即执行函数),都存在同样的问题:
1)、html不但要引入自己需要的js文件,还需要引入js文件需要的js文件。如:a.html需要使用 b.js的代码,而由于b.js中使用了c.js里的代码。所以,在a.html中必须引入b.js和c.js。这是JavaScript语言先天性的缺陷----js文件没法引入js文件。其它编程语言(java,c#,c/c++)就不存在这个问题。
2)、引入js文件的顺序问题以及异步加载问题。
为此出现了一些解决方案:
1)、前端模块化:在前端里出现了第三方的解决方案 AMD和CMD
2)、后端模块化:在后端里(nodeJS)出现了commonJS规范。
五、包和npm
1、包的概念:
在Nodejs中包由由包结构和包描述文件两个部分组成.
包结构:用于组织包中的各种文件,例如:源代码文件、资源文件
包描述文件:描述包的相关信息,例如:package.json、bin、lib等文件
2、npm
npm是随着Nodejs一起安装的一个包管理工具,它具有以下用途:
-
允许用户从NPM服务器下载别人编写的第三方包到本地使用。
-
允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
-
允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
3、npm常见命令
eg:
1.包
nodejs中包有两部分组成:包文件和包的描述信息(配置文件、json文件等...
2.NPM node package manger node包管理器
1)允许通过NPM从NPM市场下载包
2)允许通过npm将自己开发的包上传到NPM市场
3)允许通过npm上传和下载命令
3.安装
4.常见的命令
1)npm init 初始化代码工程(会在根目录下生成一个package.json的文件)
其它用法:
npm init -y
2)npm install 安装 安装命令执行之后,会在项目的根目录下产生有一个node_modules的目录(以后所有下载的包都会安装到该目录)
简化为:npm i
本地安装:将包安装到项目中
安装到项目/生产依赖:
npm install 包名 新版nodejs的写法
npm install 包名 --save 旧版写法
简化为:
npm install 包名 -S
npm i 包名 -S
安装到开发依赖
npm install 包名 --save-dev
简化为:
npm install 包名 -D
npm i 包名 -D
注意:修饰符可以在前、在后
npm i 包名 -D
npm i -D 包名
全局安装:将包安装到计算机上(默认C盘)
npm i 包名 -g
区别:
生产依赖:包不仅在开发阶段要使用,在生产阶段也要使用
开发依赖:只在开发阶段使用
本地安装和全局安装:
本地安装:适用于绝大多数项目开发包
全局安装:一般用于安装命令类型包
例子:全局安装cnpm
npm install cnpm -g
换源:
npm config set registry https://registry.npmmirror.com
4、package.json文件详解
eg:
{
"name": "node_demo2", 包名
"version": "1.0.0", 版本号
"description": "", 项目描述信息
"main": "index.js", 入口文件
"scripts": { 命令
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [], 关键字
"author": "", 作者
"license": "ISC", 许可协议
"dependencies": { 生产依赖
"cookie-parser": "^1.4.6",
"jquery": "^3.7.0"
},
"devDependencies": { 开发依赖
"express-session": "^1.17.3",
"less": "^4.2.0"
}
}
5、淘宝镜像
1)全局安装cnpm工具( 我们npm工具如何使用的,cnpm一模一样 )
npm install -g cnpm --registry=https://registry.npm.taobao.org
2)配置npm命令的源:
npm config set registry https://registry.npm.taobao.org