Node.js学习笔记--进阶之路

简介

node-Api文档
Node 是一个软件, 可以脱离浏览器, 独立执行JS文件
node特点:单线程,跨平台,非阻塞,事件驱动+回调函数
Node实现了ECMAScript标准, 所以语言跟JavaScript基本一致

    因为想成为全栈开发(前后端都可以的大拿)
    PHP等语言是阻塞的, 性能不如nodeJS
    node是事件驱动, 非阻塞的
    Node中是大量的, 事件和回调函数
    单线程(主线程单线程,后台I/O线程池)
    跨平台 (Node软件可以安装在window系统/linux系统/mac系统/等等)

开发/发布环境

1. 开发环境:  指编写代码, 时用到的环境,包含调试工具,打包工具等
2. 生产环境:  指发布到线上后的环境

安装Node

安装环境
nodejs的基础语法: js+npm模块管理器
核心模块: 文件系统IO, 网络模块, 加密, 数据流
框架: express4.x, express-generator, socket.io, koa2
数据库: mysql
运行环境: win, mac, linux, unix, 只要安装了node环境
io指的是对磁盘的读写操作(input输入和output输出)
Node仅仅对ES标准进行了实现,所以在Node中不包含DOM 和 BOM 
但是Node实现了 console 和定时器(setTimeout() setInterval())

从官网下载.msi 安装包, 双击默认下一步安装即可!
.msi: windows的安装程序(建议) 会自动配置环境变量, 在环境变量中, 当使用.msi安装后,在path中会自动添加 D:\软件\node\ 路径
二进制文件: 直接运行node命令了, 自己配置环境变量
运行命令 > node -v 显示版本号即为安装成功
注意: 环境变量修改后, 一定重启cmd
cmd终端作用: 用于操作计算机

Win常用命令

cmd终端中的命令:
cd   可以切换当前终端命令所在目录, 到后面指定的文件夹中
C:\Users\ThinkPad\Desktop>  代表你现在所处的文件夹
如果不会cd命令
先进入到目标文件夹下, 在上面输入框中敲击cmd回车, 也可以打开当前路径的终端窗口
cls (windows)   clear (mac) 清空当前终端
路径/命令, 先敲击开头的1-3个字符, 然后用tab键补全, 多次按tab会切换可以使用的选项

启动命令行窗口:  开始菜单->搜索框->输入cmd->回车
命令行窗口(CMD): 其实就是用命令, 操作我们的电脑..
cd: 进入到指定目录下
cls: 清屏
start: 启动文件资源管理器 (start .)
dir: 显示当前文件夹下所有文件和文件夹信息
md: 创建一个文件夹
rd: 删除一个文件夹
mkdir: 新建一个文件夹
. 代表当前路径
.. 代表上一级文件夹路径
技巧: 快速的在终端切换到目标文件夹下, 先打开目标文件夹, 在当前目录下 shift+右键->在此处打开命令窗口

helloNode

使用node命令, 可以直接执行一个js文件.(证明: 脱离浏览器)
js文件代码: console.log('hello, nodejs'); , 用node命令来执行此js文件查看效果
注意: 文件,不要叫node.js, 因为在执行node命令时, 会寻找node命令文件, 冲突
	打开cmd终端
	终端目录, 切换到目标js文件所在目录
	node  js文件名 
	回车执行, 查看结果

Node全局变量

顶层对象

Node执行的js脚本文件中, 我们的顶层对象不再是window了, 而是global对象

console.log(global);

全局变量

__filename: 当前模块文件的绝对路径 (带文件名)
__dirname: 当前模块文件夹的绝对路径

console.log(__filename);
console.log(__dirname);

二进制

计算机中, 数据都是以2进制(0, 1)传输
二进制: 0 1
八进制: 0 1 2 3 4 5 6 7
十六进制: 0 1 2 3 4 5 6 7 8 9 A B C D E F (大小写均可)
几进制: 逢几进位

Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

// 前端Javascript里, 装载数据
// 数组装载: 字符串, 数字, 布尔值, 数组, 对象, set, map, Symbol, Error, undefined, null  (装载不了二进制数据)
// nodejs中, 定义了一种专门存储二进制数据的容器类型, 叫Buffer  (类似于数组Array)  (Buffer表现打印的时候, 是以16进制, 显示的二进制数据)
//===示例=====
// 1. Buffer.from()  把字符串转换成Buffer二进制数据
let buf = Buffer.from('豪子');
console.log(buf);//<Buffer e8 b1 aa e5 ad 90>
//(buffer打印不会以0和1打印, 而是优化后, 以16进制数打印出来)
// 2. Buffer和Array很像, 都有索引下标来使用
console.log(buf[0]); //e8
console.log(buf[1]); //b1
console.log(buf[2]); //aa

// let arr = Array.from(buf)
// console.log(arr) //[ 232, 177, 170, 229, 173, 144 ]

// 3. 文件里的内容是由二进制组成, 需要用Buffer来接收, 输出到控制台上, 我们想看的不是二进制数据, 而是想看UTF-8编码的字符串  (需要把Buffer -> 字符串)
// .toString()
let str = new Buffer([0xe8,0xb1,0xaa,0xe5,0xad,0x90]);
console.log(str.toString(),buf.toString());

// 注意: [] 是单纯的数组, 是不能装在二进制数据的, 即时装了也会被转换成10进制展示
// 所以, 需要用Buffer来装我们的二进制数据
// [] 相当于是 new Array()的语法糖
// 想要Buffer数组, 需要new Buffer(), 因为Buffer没有语法糖
// 总结: Buffer是装在文件读出的二进制流数据, 调用.toString()会转换成我们能读懂的字符串

 特点

Buffer无需引入模块, 直接使用
Buffer结构和使用, 都与数组类似
在内存中, 数组不能存放二进制数据, 而Buffer则专门用于存放二进制数据
Buffer中的二进制数据, 打印时以16进制显示
常用于文件相关的操作上

注意事项

Buffer中每一个元素的范围是从00 - ff(十六进制), 对应  0 - 255(十进制) 00000000 - 11111111 (二进制)
Buffer中的一个元素,占用内存的一个字节,  一个英文字符串占1字节, 一个中文占3字节
Buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存的直接操作

常用方法

Buffer.from(str) 将一个字符串转换为buffer
length  打印buffer对象长度(其实也是所占内存大小, 单位为字节)
Buffer.alloc(size) 创建一个指定大小的Buffer, 还可以用for循环
可以向数组一样, 往里面每一位赋值, 甚至是取值都可 (但是注意了, 每一位最大范围是255)
buf.toString() 将buffer流中的二进制数据转换为字符串 ([0xe6, 0x99, 0x9a, 0xe4, 0xb8, 0x8a, 0xe5, 0xb0, 0x8f, 0xe6, 0xa0, 0x91, 0xe6, 0x9e, 0x97, 0xe8, 0xa7, 0x81])

events模块

模块: 其实类似于前端浏览器里引入的js功能文件, 里面拥有很多属性和方法供我们直接调用
 Node.js 核心 API 基于异步操作 例: http模块的createServer会在每次有新连接时触发事件和回调函数

模块核心功能

on()    : 监听器, 用于将一个函数绑定到自定义事件上
once() : 监听以后, 只会被emit触发一次
emit() : 触发器, 用于触发自定义事件

// 前端Javascript其实也是靠事件驱动的
// click等点击事件 -> 点击时 ->  触发回调函数
// setInterval计时器事件 -> 等待指定时间 -> 触发回调函数
// ajax事件 -> 等待网络请求结果 -> 触发回调函数
// 后端Nodejs 也是靠事件驱动的
// fs读取指定的文件/文件夹 -> 读取事件结果 -> 触发回调函数

// 事件驱动 + 回调函数  ->  形成 非阻塞的代码   (一般情况下这种组合拳适用于异步操作)

// events模块, 就是nodejs中的一个事件模块, 用于自定义事件使用
const EventEmitter = require('events').EventEmitter; // 1. 从events模块中, 引出类 EventEmitter
const ev = new EventEmitter(); //2. 实例化一个事件对象
// 因为其他的类, 内部其实都实现了events模块, 我们要了解事件是如何监听的, 如何触发的
ev.on("dyhck", (result) => { // 3. 监听自定义事件名字, 当事件被触发时, 会开始执行参数2的回调函数
	console.log(result);
});

//一次性
ev.once("dyhck", () => {
	console.log('我是一次性的'); // 在每次执行完node运行过程中只会执行一次
	// 类似于Jquery里的one方法: 刷新一次, 网页代码就会重新执行
	// Node每次 node xxx.js文件名, 就算重新执行了一次
})

setInterval(() => {
	ev.emit("dyhck", "返回信息"); // 4. 异步操作结果, 靠emit()来触发事件, 同时传递参数(参数是可选的)
}, 3000); // 定时器模拟异步任务(例如文件读取/Ajax)
// on: 监听事件
// emit: 触发事件

基础使用+传参

let EventEmitter = require('events').EventEmitter;
let emitter = new EventEmitter();

emitter.on("move", ()=>{
    console.log("gogogo");
}) 
emitter.once("move", () => {
    console.log("只有一次");
})   // 监听以后, 只会被emit 触发一次
setInterval(()=>{
    emitter.emit("move")  //  当事件被触发时, 绑定在这个事件上的函数都会被同步调用
}, 1000)
//传参使用
emitter.on('someEvent', function(arg1, arg2) {
    console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');

FS

文件系统(File System)

文件系统简单来说就是通过Node来操作系统中的文件/文件夹
使用文件系统,需要先引入fs模块,fs是核心模块,直接引入不需要下载

文件操作

权限

Flag 描述
r 以读取模式打开文件。如果文件不存在抛出异常。
r+ 以读写模式打开文件。如果文件不存在抛出异常。
rs 以同步的方式读取文件。
rs+ 以同步的方式读取和写入文件。
w 以写入模式打开文件,如果文件不存在则创建。
wx 类似 'w',但是如果文件路径存在,则文件写入失败。
w+ 以读写模式打开文件,如果文件不存在则创建。
wx+ 类似 'w+', 但是如果文件路径存在,则文件读写失败。
a 以追加模式打开文件,如果文件不存在则创建。
ax 类似 'a', 但是如果文件路径存在,则文件追加失败。
a+ 以读取追加模式打开文件,如果文件不存在则创建。
ax+ 类似 'a+', 但是如果文件路径存在,则文件读取追加失败。

简单写入

// 同步写入
fs.writeFileSync("./fs-01.txt","fs写入内容",{flag:'w',encoding:'utf8'});
//异步方式
fs.writeFile("./fs-01.txt","fs写入内容");

var fs = require("fs"); // 1. 引入fs模块
// 1. require()是全局变量的一个函数, 专门用来引入其他的js文件 相当于 let $ = $;  <script src="jquery.js"></script>
// 此fs模块(fs.js文件)是安装node环境自带的
// 2. fs模块作用: 用于读取文件, 写入文件, 创建文件夹, 删除文件夹, 检测文件夹 (一个和文件+文件夹 打交道的一个功能文件, 里面有很多的方法供我们使用)
/**
 * 2. 向文件内写入内容(异步)
 * 参数1: 文件路径
 * 参数2: 写入内容
 * 参数3: 配置模式: (文件操作标识(a代表追加,如果文件不在则创建, 编码格式)
 * 参数4: 回调函数, 异步读取后触发此方法
 */
fs.writeFile("hello3.txt", "这是通过writeFile写入的内容", {flag: "a", encoding: 'utf8'}, function (err) {
	if(!err){
		console.log("写入成功");
	}else{
		console.log(err);
	}
});

fs.writeFileSync()
fs.writeFileSync("hello3.txt","这是通过writeFile写入的内容",{flag:"a",encoding:'utf8'})

简单读出

//===fs.readFile()
var fs = require("fs"); // 1. 引入fs模块
fs.readFile("./txt/hello.txt", function (err, data) { // 2. 设置读的文件路径, data读出的buffer数据
    if (!err) {
        console.log(data.toString());
    }
});

//===fs.readFileSync()
fs.readFileSync("./txt/hello.txt").toString()

文件重命名

// 重命名 同步
fs.renameSync("./fs-01.txt","./01-fs改名.txt");
//异步
fs.rename("./fs-01.txt","./01-fs改名.txt");

fs.renameSync("./txt/rename改的文件.txt", "./txt/再改一下.txt")

读取文件

// 读取文件夹 同步
let arr = fs.readdirSync("./01");
//异步
fs.readdir("./01");

fs.readFileSync('./nodedyh.md',{flag:'r',encoding:'utf8'});// 如果不指定econding, 那么读出来的就是Buffer数组里装载文件里的16进制的数据(底层二进制)
console.log(result.toString());

删除文件

//删除文件 同步 只能删除文件, 不能删除文件夹
fs.unlinkSync("./01-fs改名.txt");
//异步
fs.unlink("./01-fs改名.txt");

 文件夹操作

创建文件夹

// 创建文件夹
fs.mkdirSync("./01/fs文件夹",{recursive: true});
//{recursive: true} 加上以后, 可以递归创建文件夹(无论嵌套多少层)
fs.mkdir("./01/fs文件夹",{recursive: true});

var fs = require("fs"); // 1. 引入fs模块
fs.mkdir("./dir/gogo", {recursive: true}, (err) => { // 2. 创建文件夹
    if (err) console.error(err);
});
// {recursive: true} 设置后, 可以同时创建多层的文件夹

读取文件夹

//=====fs.readdir()
let fs = require('fs');
fs.readdir('./dir', function (err,files) {
    if(err){
        throw err
    }
    console.log( files )
});

删除文件夹

// 删除文件夹 同步
fs.rmdirSync("./01");
//异步
fs.rmdir("./01");

fs.rmdir("./dir/helloDir", (err) => {
   if (err) console.error(err);
});

注意: 只能删除空的文件夹, 有隐藏文件也不行
如果要删除文件夹, 需要用代码先遍历里面的一切,删除掉里面的一切, 最后再删除此文件夹

检测路径 文件/文件夹

//===fs.stat()===异步
fs.stat("./dir/gogo", (err, stats)=>{
    if (err) console.error(err);
    console.log(stats.isDirectory()); // 文件夹   ->  true
    console.log(stats.isFile());      // 文件     ->  true
});

//========示例=========同步==
let thePath = "./01";
let thePath2 = "./01/01.txt";
let s = fs.statSync(thePath);// 分析路径, 返回状态对象
// 2个方法(其中一个, 来判断是文件/文件夹)
console.log(s.isFile());// false
console.log(s.isDirectory());// true

try+catch

const fs = require("fs")
// 1.异步 --- 捕获错误  -- 回调函数里
// (1): 异步代码不会耽误主线程代码继续执行
// (2): 异步中的报错, 都会反馈到回调函数中, 由系统调用回调函数, 传递第一个错误信息数据
fs.readdir("./100", {}, (err, files) => {// files接收成功的结果
    console.log(err);
});
console.log("下面代码");

// 2. 同步 --- 捕获错误 ---  try+catch
// (1): 主线程遇到错误, 被阻塞了, 直接抛出异常到主线程中, 阻止代码继续向下执行
// (2): try+catch 捕获运行时的错误
try{ // 这里放入可能未来会报错的代码, 如果没放到这里, 是不会捕获到的
    // 执行过程: 如果这里有错误, 直接跳转到catch里执行, 然后继续执行主线程代码
    // 如果没有错误, try执行完了, 不会触发catch, 而是继续执行主线程代码
    let files = fs.readdirSync("./100");
    console.log(files);
} catch (err) { // (3): 自己捕获了错误, 主线程就不会阻塞, 继续向下执行
    console.error(err);
}
console.log("下面代码还会执行吗?");

模块简介

在Node环境中,每一个js文件就是一个模块
在Node环境中,每一个js文件中的js代码都是独立运行在一个函数中, 并且不是全局作用域,所以一个模块的中的变量和函数在其他模块中无法访问
分为三步: 模块定义(导出), 模块标识, 模块引用(导入)

// 什么是模块:
// 1. 在Node环境中,每一个js文件就是一个模块
// 2. 在Node环境中,每一个js文件中的js代码都是独立运行在一个函数中, 并且不是全局作用域,所以一个模块的中的变量和函数在其他模块中无法访问
// 3. 分为三步: 模块定义(导出), 模块标识, 模块引用(导入), 使用
// 模块标识分为2种:  (模块标识就是模块的名字, 影响require()时, 里面的写法)
// 第一种: 核心模块和npm管理的模块 都是直接写模块名
// 第二种: 自定义模块,  需要写相对路径
const theObj = require("./dyhMod-01"); // 如果后缀是.js可以省略
console.log(theObj.sum(2,3));
console.log(theObj.PI);

const theObj2 = require("./dyhMod-02");
console.log(theObj2.sum(3,3));

//4
// 概念1: 模块之间都是独立的, 如果不导出, 外部是无法直接访问此模块内任何变量
// 概念2: 因为每个模块在运行时, 会被套住一个函数级作用域(为了防止模块之间变量重名)
/*function(__dirname, __filename, require, exports, module) {*/
    const PI = 3.1415926;
    module.exports = {
        PI
    }
/* } */

核心概念 *

导出exports

采用CommonJS规范, exports作用, 向外暴露变量和方法, 只将变量或方法设置为exports的属性即可

exports.PI = 3.1415926;
exports.sum = function(a, b){
    return a + b;
}
exports.circleS = (r) => {
    return (2 * PI * r);
}

// 注意: exports.xxx  是module.exports的语法糖
// 下面这里其实就是一次性给exports直接赋值了, 会覆盖掉上面exports的值 (因为module.exports === exports)
// module.exports = {
//     PI,
//     sum,
//     circleS
// }

导出module.exports

exports和module.exports等价的
    注意1: module.exports = {}; 会覆盖掉exports上的东西
    注意2: module.exports.xxx 则不会覆盖掉exports上的东西
实际暴露外部的是module.exports, 而exports只是辅助工具
    口诀: 部分exports, 全部module.exports = {}

// 这是我要定义的一个js模块 (类似于前端定义的工具js文件)
// 封装模块里的方法
const PI = 3.1415926;
function sum(a,b){
	return a+b;
}

function circle(r){
	return 2 * PI *r;
}
// 1. 准备好属性/方法
// 2. 要导出你想被外部使用的属性/方法  (使用固定的全局变量module来导出东西, 配合exports使用)

// let obj = {
// 	PI,
// 	sum,
// 	circle
// }
// 把当前这个对象 导出出去, 让外部人使用 (此js里的所有属性和方法, 需要导出, 别人才能导入后使用)
module.exports ={
	PI,
	sum,
	circle
};

导入require

采用CommonJS规范, require作用, 引入模块里暴露出来的属性/方法供我们使用
1. 核心模块: 可以直接写模块名, 引入
2. 自定义模块: 需要写相对路径 "./开头"
3. npm下载的模块: 可以直接写模块名, 引入

require() 中可以传入一个模块标识符(模块名字), 或相对路径

模块分类

核心模块

由Node引擎提供的核心模块 (fs模块, events模块 , 还有http, path, url等模块)

自定义模块使用

由用户自己创建的模块js文件
文件模块的标识就是文件的路径(相对路径)

//=====================使用=================================
// 模块: 定义导出, require导入 (是一个具体的.js文件)
// 模块包: 定义导出, require导入 (导入的是一个文件夹)
//  决定导出的内容, 在package.json中的main属性指定的入口文件, require导入的就是这个入口文件里module.exports导出的内容

// 情况1: 导入一个.js 模块文件  到具体文件
const req = require("./dyhModel/mySum");
console.log(req.mySum(1,2));

//情况2:导入一个 模块包 包含模块的文件夹
const reqObj = require("./dyhModel");
console.log(reqObj);
console.log(reqObj.circle(6));


//=========自定义模块包-dyhModel 文件结构
-dyhModel
	-index.js ->入口文件
	-circle.js ->模块01
	-mySum.js ->模块02
	-package.json 配置文件
	
//========index.js 内容	
// 自定义模块包: 其实就是把自己封装的各个功能模块
// 整合成一个模块包文件夹
// 1. 初始化package.json
// 2. 确认入口的.js文件  (index.js)
// 3. 在package.json的main属性上, 设置入口文件(如果不写, 默认就是index.js)
const circle = require("./circle");
const mySum = require("./mySum");

//合并成一个对象 不是对象的加 {}
const obj = Object.assign({},circle,{mySum});
module.exports = obj;
//===========circle.js 内容
const PI = 3.1415926;
function circle(r){
	return 2 * PI *r;
}
module.exports ={
	PI,
	circle
};
//===========mySum.js内容
exports.mySum = function(a, b){
    return a + b;
}
//===========package.json 配置信息
{
  "name": "dyhmodel",
  "version": "1.0.0",
  "description": "自定义模块包",
  "main": "index.js",  //入口文件
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dyh": "npm -version" //自定义命令
  },
  "author": "by dyh",
  "license": "ISC"
}

NPM模块

下面会讲npm 包管理器, 是被npm管理起来的模块

Node模块全局变量

在node中, 有一个全局对象global, 它的作用和网页中window类似,在node中一定要记住是没有BOM和DOM的, 但是模拟了, setTimeout和setInterval等都是global的属性
    注意, 在运行时, 每个模块js都会被套上一个这样的函数, 被系统传入5个参数

function (exports, require, module, __filename, __dirname) {  
}

exports: 该对象用来将变量或函数暴露到外部
require: 用于引入外部的函数
module: module代表的是当前模块本身, exports最终要挂载在它身上

__filename: 当前模块文件的绝对路径 (带文件名)
__dirname: 当前模块文件夹的绝对路径

npm*

(Node Package Manager) node的包管理器
包 -> 一个/多个js模块组成

1. 
模块: 就是一个独立的.js文件
(模块)包: 拥有多个封装的js模块文件, 形成的一个文件夹 (我们叫这个文件夹叫模块包)
以后写的node项目文件夹, 其实就是一个大模块包

2. 
npm: (Node Package Manager) 主要负责 (上传, 下载, 查询, 删除)我们要使用的包
因为一个项目开发, 需要用到很多的工具, 而我不想写这些现有的工具(时间处理/jQuery/Swiper)
我们想下载这些工具包, npm 就是负责干这个活  (npm 其实也是一个命令)
node环境安装时, 会把npm 一并下载安装, 测试你有没有npm功能: cmd中命令: npm -v (-v是-version的简写)

3. npm使用
初始化+下载
把npm 当成管家, 让它去 下载 需要的模块包
(1) 先要明确模块包的名字 (百度看到的/别人告诉我的/书上写的)
(2) 去npmjs.com网站上, 确认包名以及, 版本号  (确认上次更新/下载量 但是不绝对, 如果找到的是一个偏僻的模块包, 确认名字就行了)
(3) cmd切换到当前文件/当前工程的文件夹中, 因为npm下载都是靠命令来操作的
(4) 要确认当前文件夹中是否拥有, package.json记录文件 (记录你下载了哪些包) (如果没有, 运行npm init命令, 初始化一个package.json记录文件)
Package name (当前模块包的名字, 小括号里的是默认值, 但是不能用中文, 但是可以用-)
version (是当前工程, 项目的版本号)
description 当前工程的一个说明
entry points 当前工程的入口文件 (但是工程没有入口文件, 只有封装的工具包, 需要指定入口文件, 所以这里直接回车)
(5) 在第2步, 确认了安装模块的命令, 直接在cmd中使用即可
npm i jquery
或者用 npm install jquery  (i或者install都可以) 作用: 从镜像地址直接寻找jquery, 下载下来

查看:
查看package.json是否记录了你刚下载的模块名和对应的版本号
注意在cmd中, 在哪个目录下, 执行的npm i 命令就会下载到那个目录下
注意: 所有模块包都会把具体的文件夹+文件代码, 下载到node_modules目录中统一管理(node_modules是npm自己创建的, 并非我们自己手动创建)
注意: package-lock.json 
功能1: 锁定最大版本号(例如Vesion.1.9.1  最大版本是1, Version3.5.1 最大版本是3, 再次运行npm i xxx模块包名, 会安装最大版本号下的最新版本)  注意: npm i xxx@版本号 可以忽略lock文件
功能2: 加快版本的下载速度

作用

通过npm可以对node中的包进行上传、下载、搜索, 删除)等操作
npm功能会在安装node环境时,自动安装
建议切换成国内的镜像, 下载的快, 命令: npm config set registry https://registry.npm.taobao.org (彻底修改, 以后都不用再执行此命令了)
使用命令 npm config list  查看registry选项, 是否变成了taobao.org的地址

npm下载的包搜索和教程

常用命令

  • npm -v 查看npm的版本

  • npm init 初始化项目(创建package.json), 需要用户输入项:

    • ctrl + c 可以随时终止终端里正在执行的命令

    • npm init -y: -y的意思代表所有项都使用默认值, 如果报错了, 则执行失败,还得用npm init 自己来一个个输入 (建议大家, 当前文件夹不要起中文和特殊符号)

    • 所有项, 直接回车, 默认使用括号里的值/空

      输入项 含义 备注
      package name 包名字 默认所在文件夹名,不能包含特殊符号和中文
      version 版本号 默认1.0.0, 包每次更新都会有版本号增加
      description 描述说明 默认空字符串
      entry point 包入口 默认文件夹下的index.js或者其他js文件
      test command 测试命令 默认空字符串
      git repository 项目git地址 默认空字符串
      keywords 关键词 默认空字符串, 用于别人搜索包
      author 包作者名 默认空字符串
      license ISC开源许可字符串 默认ISC

产物讲解

  • package.json: 包的重要组成部分, 包含了npm相关的所有信息, npm自定义命令, 列出项目需要的所有包的名字和对应版本 (给别人传npm管理的项目, 不要传node_modules, 而是要传带package.json文件的整个项目源码)

如果npm install 下载了一个第三方包以后, 会额外产生一个文件: package-lock.json

  • package-lock.json: 是npm5以后引进, 负责锁定最大版本号, 防止不同项目出现不同的包版本.而且记录了下载地址, 加快npm下载 (无法阻止指定版本的安装)

  • 补充package.json里字段解释:

    • scripts里面配置的命令, 是给npm扩展的自定义命令, 只能在package.json文件所在的目录使用

    • npm (run) xxx; 执行script里配置的 自定义命令 run可写可不写

输入项 含义 备注
scripts 指定npm可以运行的命令  自定义命令 自定义命令
dependencies 发布环境依赖的 第三方模块包名 写完项目线上环境
devDependencies 开发环境使用的 第三方模块包名 本地开发时候环境
  • npm i/install 包名 ----- 安装包 默认安装最新版本 (/代表或者)

  • npm i/install 包名@版本号 ----- 安装包 安装指定版本号的包

    • http://npmjs.com查找你要下载的包的版本, 注意周的下载量, 如果很少可能你找错了, 一定要知道有的版本号, 你才能正确下载

    • 注意@指定的版本, 不受package-lock.json的 锁定

  • npm i/install 包名 --save ----- 安装包 添加依赖到dependencies列表中(不写默认就是这个)

  • npm i/install 包名 --save-dev ----- 安装包, 添加依赖到devDependencies列表中

  • npm i/install 包名 -g ----- 全局安装包(前提: 工具类(express-generator)的包安到全局, 普通包不要安到全局)

  • npm i/install ----- 安装当前项目里package.json文件记录的所有包名, 对应的包(不要传递node_modules因为它很大, 所以别人拿到带package.json文件的npm管理的项目, 先执行npm install来下载所需要的所有第三方包(包名都在package.json中记录着)

    • 例如: cnpm来替代npm 安装我们的模块: 命令: npm install -g cnpm --registry=https://registry.npm.taobao.org (注意和我们逐级查找模块要区分开)

  • npm s/search 包名 ----- 搜索包 (必须在官方镜像下)

  • npm uninstall 包名 ----- 卸载哪个包 或uni

  • npm r/remove 包名 ----- 删除一个包

  • npm config list ----- 查看npm配置信息(可以看全局npm安装位置, 镜像地址)

time-stamp

这是一个时间格式化的包, 可以去https://www.npmjs.com/ 找到你想要的包, 和使用文档

包的使用: 下载 & 引入 & 使用
const timestamp = require('time-stamp'); // 引入包
console.log(timestamp());// 2019-02-13
console.log(timestamp.utc());// 2019-02-13
//自定义时间格式
console.log(timestamp('YYYYMMDD'));  // 20190213
console.log(timestamp('YYYY年MM月DD日')); // 2019年02月13日

作用域*

下载好的包都在node_modules, 可以应用在当前文件夹, 和所有的子文件夹项目中

npm i xxx -g 只能安装命令行工具包, 到 C:\Users\ThinkPad\AppData\Roaming\npm\node_modules\  (如果你电脑里没有找到AppData, 它可能是一个隐藏文件夹)  (就是可以直接在终端使用命令的工具包)

npm i xxx 普通安装的模块包, 没有全局的概念, 只有父级的概念, 当前工程中没有找到require要引入的第三方包名, 就会一直向父级查找, 直到根目录为止, 如果还没找到就抛出错误  (打印console.log(module) 查看path)

npm自定义命令

npm内置的命令: npm init 、 npm install .....
npm的自定义命令:
(1): 在"当前目录"中的package.json中的 scripts里自定义命令的名字, 和对应要执行的代码/命令
(2): 执行自定义命令 用 npm run 自定义命令的key名
(3): 实际上, 在终端中还是执行了右侧value的代码/命令

使用场景: 可以给很长的命令, 配置一个简短的自定义名字

//=====示例===========
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dyh": "npm -version"
  }

全局工具模块

可以查看全局安装的模块的位置, 但是要注意, 只有工具模块才可以生效
C:\Users\ThinkPad\AppData\Roaming\npm\node_modules  全局包(模块)安装的地方

注意: 1 npm需要有node环境才能使用哦
      2. npm其实也是一个模块包, 只不过它被配置了命令行命令来使用 位置: D:\软件\node\node_modules\npm
      3. npm i -g 安装的带命令行的模块包, 都会部署到 C:\Users\ThinkPad\AppData\Roaming\npm下, 然后连接到电脑的cmd终端中, 直接调用命令行

服务器

局域网-IP地址

在一个入口IP中, 设置的分发网络, 可以让多台设备在这个小网络中共用这个入口IP进行上网
局域网的IP只在局域网内有效  (也叫内网, 上的外网叫互联网)

本地:localhost == 127.0.0.1 本地环回地址

端口号

通过ip地址找到对应的服务器计算机,但是服务器上是有很多功能的,比如网页服务, 数据库服务, 邮箱服务, 通信服务, 自定义服务等等, 每个应用程序服务利用端口号, 加以区分
  ip + 端口  确认你访问的功能
- web网页  ---  80
- mysql服务 --- 3306
- mongodb服务  --- 27017
- ftp服务  ---  21
- smtp服务  --- 25    等等  以上端口不是固定的, 可以随意更改, 只是默认

注意: 
0-1023: 系统端口,有系统特许才能使用 (node拿到权限后也可使用)
1024~65535为用户端口:
  1024-5000: 临时端口,一般的应用程序进行通讯
  5001-65535:服务器(非特权)端口,给用户自定义端口

服务器和浏览器

浏览器 -> 输入网址  ->  服务器响应  -> 返回HTML等资源内容   (这也是上网的过程)
网页访问过程:
注意: 浏览器上什么都没有, 都是通过网址来访问, 网址对应的服务器会返回内容给浏览器渲染展示
本地双击html文件运行, 无法查看cookie等, 找不到相对的资源
也就是说, 浏览器-> 根据url -> 访问服务器上资源 -> 拿到数据 -> 根据规则展示 给你看
浏览器: 就是用于请求&展示 的一个工具而已

以前访问一台服务器电脑, 需要使用ip地址, 但是ip地址是4段数字, 而且很难记忆, 所以才出现了域名这个东西
​    域名工作的过程:  域名 ->  IP地址,   你访问域名 实际上访问的就是它所对应的ip地址
​    例如: 百度ip: 39.156.69.79  ->  baidu.com
​    例如: 本地电脑 ip: 127.0.0.1  ->  localhost  (固定)
​    注意: 域名也需要购买 和申请及备案, 默认所有的域名都应该在DNS中配置域名解析

其他web网页服务

Apache  (lampp/xmpp/xampp)  --- 一般PHP后台代码, 运行的环境在Apache上
Tomcat  --- Java代码 -  运行在Tomcat上
Node ---  node.js语言创建的web网页服务

Node创建web网页服务

拥有web网页服务功能的计算机,  可以叫做web服务器,  也可以叫http服务器
这里, 借助Node.js的核心模块(安装Node就带了), http模块, 来创建web网页服务
web服务器/http服务器 ->  这台计算机服务器中, 有web网页服务功能, 可以提供浏览器要访问的资源

// 在Node环境上, 使用node.js借助http模块, 来搭建一个web网页服务
// 1. 引入http模块(核心模块, 安装完Node自带的, 跟fs, events等一样都是核心)
const http = require("http");
// 2. 调用方法生成一个web网页服务对象
const setver = http.createServer((req, res) => {
    // resquest: 请求对象 (里面有很多的属性和方法) -> 包含的是浏览器发送过来的一些信息
    // request.url: 是浏览器要请求的url地址
    // response: 响应对象 (....................) -> 可以给浏览器返回/设置一些信息
    // res.writeHead() 代表响应时, 写入头部的信息(告诉浏览器要怎样处理我给你的数据)
    res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});// 写入响应头部内容给浏览器
    // Content-type: 内容类型, text/html html文本类型, 这些文本都以utf-8编码展示
    // 200 状态码, 告诉浏览器, 你本次请求是成功的  (如果是, 404失败的)
    //打印 请求地址和方式
    console.log(req.url,req.method);
    // 3. 此回调函数, 是当浏览器请求这个node的web网页服务时, 会触发此函数执行
    console.log("浏览器发起了一次http请求");
    res.end("{hello:'node-http-你好dyh'}");// 给浏览器响应(返回)一个内容, 并结束本次响应
    // res.en
posted @ 2020-05-10 19:06  JackieDYH  阅读(3)  评论(0编辑  收藏  举报  来源