nodejs01

(啊我真棒,学完了这节)
nodejs是运行在服务端的js.
把我们平时用到的js文件放在node上执行,它就是nodejs.
在终端执行js文件:

node 文件名.js
vscode终端快捷键:ctrl+`

一.安装

在node官网,一般选稳定版:


image.png

检查是否安装成功:

node -v

或者用homebrew安装(mac).
如果在windows下显示node不是内部命令, 则需要配置环境变量:
windows配置环境变量: 计算机--属性--高级系统设置--环境变量, 在系统变量里找到path,加上我们要添加的新路径(和之前的用分号隔开),然年确定. 之后关了终端重新打开一下,输入命令就可以用了.


image.png

二.搭建node服务器

新建文件http.js:

const http = require("http")
const server = http.createServer((req, res) => {
    res.write("hello world")
    res.end()
})
server.listen(3000) // 3000是端口号

然后在终端执行(node启动成功之后没任何提示,没报错就是成功了哈哈哈):

node http.js

访问服务:
本机访问:方法一. http://localhost:3000/
方法二. 127.0.0.1:3000
方法三. ip:3000(ip是自己电脑的ip,在终端输入ipconfig就能看到)
同一局域网下的其他电脑访问:ip:3000

image.png

每次改动之后都要重启服务之后客户端才能刷新, 所以我们安装nodemon,可以实现热更新:

npm i nodemon -g

安装成功之后用nodemon启动服务:

nodemon http.js
创建服务的就是服务端,启动服务的就是客户端.

三.node中的模块化

我们平时写js的时候,变量命名重复等会引起变量污染.在nodejs里,用commonjs规范,把代码划分成不同的模块,每个模块有自己独立的命名空间,相互之间不会产生影响,代码也变得清晰可读和易于维护.通过模块之间的相互引用.
客户端的模块化工具主要有:AMD(sea.js), CMD(require.js),
服务端的模块化工具commonjs是node自带的.

模块之间引用: 导出module.exports,引入require('xxx')

导出(/home/index.js):

let a = 10 
class Person{
    constructer() {
        this.name = "张三"
    }
    hobby() {
        console.log("喜欢篮球")
    }
}

module.exports = {  // 可以导出变量和构造函数
    a,
    Person
}

// 也可以用exports导出:
// exports.a = a
// exports.Person = Person
// exports是module.exports的引用 module.exports= exports

引入(inex.js):

let home = require('./home') // 相当于require('./home/index.js')
console.log(home.a)  // 10
let zhngsan = new home.Person
zhngsan.hobby()   // 喜欢篮球

四.node中的node-modules

从外部引入的node模块,一般都会放在文件夹node_modules里,
从node_modules引入模块的时候,不用加./(引入文件和文件夹的时候需要):
index.js:

// require("nodetest")
let {a, b} = require("nodetest")
console.log(a)

/node_modules/nodetest/main.js:

console.log("main.js")
module.exports = {
    a: 10,
    b: "bbb"
}
文件目录结构

package.json是描述功能性文件.

五.npm包管理器

以上,是引入模块的三种方法:
1.引入文件:require('./a.js')
2.引入文件夹:require('./home') // 默认引入./home/index.js,在该文件里引入文件夹下所有文件,则可通过 require('./home')引入整个文件夹
3.引入node_modules下的模块:require("nodetest") //注意前面没有./
引入第三方模块也是放在node_modules下面,直接引入,不用加./, 引入内置模块(如http)的时候,不用放在node_modules文件夹下,直接通过require("http")引入.
npm:包管理器,用来安装第三方模块,也可以上传自己的包https://www.npmjs.com/

六.npm常用指令:

npm install xxx// 安装模块
npm init // 初始化项目,新建package.json文件(一直回车就可以)
npm i // 是i是install的简写,用法同上
npm uninstall xxx// 删除模块
npm i xxx --save // 安装模块并将版本信息加在package.json文件的dependencies(运行依赖)里,这样别人拿到项目只用npm i就能安装所有依赖
npm i xxx -S // -S是--save的简写,用法同上
npm i xxx --save-dev // 版本信息会加在package.json文件的devDependencies(开发依赖)里
(开发依赖是只有开发时需要,上线运行的时候不用,比如sass,less等. 运行依赖是都需要,比如query,vue,react等.)
npm i xxx -D // -D是--save-dev的简写,用法同上
npm update xxx // 更新
npm i [email protected] // 安装指定版本的依赖

依赖会安装在当前项目下的node_modules文件夹里,如果当前目录没有node_modules,会往上一层目录查找,直到电脑的根目录(npm root -g命令可以看到是哪个).只要往上某一层node_modules里有需要的依赖,都可以使用

npm root // 查看当前项目下的node_modules路径
npm root -g // 查看根目录下的node_modules路径
npm i xxx -g // 全局安装,会被装在root目录下,这样子所有项目都可以使用(不加-g只会装在当前项目里)

七.fs文件操作

fs模块也是内置模块,用来操作文件

1.文件操作
(1).文件写入:fs.writeFile()
const fs = require("fs")
// 1.文件写入
fs.writeFile('1.txt', '我是写入的内容11111', {flag: "w"}, function(err) { // 第三项可以不写 不写默认{flag: "w"}
    // flag:  a追加写入  w写入  r读取 
    // err是错误信息
    if(err) {
        return console.log(err)
    }
    console.log("写入成功")
})
(2).文件读取:fs.readFile()
// 文件读取
fs.readFile('1.txt', 'utf8', (err,data) => { // 如果不加utf8,读取到的会是Buffer格式,即node里的二进制
    if(err) {
        return console.log(err)
    }
    console.log(data)
    // console.log(data.toString()) // 如果是Buffer格式,加上.toString()就可以转成字符串格式
})
#不管是文件写入还是文件读取,都是异步的,如果要改成同步格式,则在后面加上Sync(目录操作也是): fs.writeFileSync(),fs.readFileSync()
// 同步写法
let data = fs.readFileSync("1.txt")
console.log(data.toString())
(3).修改文件名:fs.rename()
fs.rename('1.txt', '2.txt', err => {
    if(err) {
        return console.log(err)
    }
    console.log("修改成功")
})
(4).文件删除:fs.unlink()
fs.unlink('2.txt', err => {
    if(err) {
        return console.log(err)
    }
    console.log("删除成功")
})
(5)文件复制:fs.copyFile()
fs.copyFile('index.js', 'myindex.js', err => {
    if(err) {
        return console.log(err)
    }
    console.log("复制成功")
})
2.目录操作
(1).创建目录:fs.mkdir()
fs.mkdir("11", err => {
    if(err) {
        return console.log(err)
    }
    console.log("创建成功")
})
(2).修改目录名称:f.rename()
fs.rename("11", "22", err => {
    if(err) {
        return console.log(err)
    }
    console.log("修改成功")
})
(3).读取目录内容:fs.readdir()
fs.readdir("22", (err, data) => {
    if(err) {
        return console.log(err)
    }
    console.log(data) // [ '1.html', '2.txt' ]
})
项目目录结构
(4).删除目录(空文件夹/目录): fs.rmdir()
fs.rmdir('home', err => {
    if(err) {
        return console.log(err)
    }
    console.log("删除成功")
})
(5).删除非空目录:

!!!!!通过nodejs删除的文件不会经过回收站,谨慎删除!

// 思路: 先把文件夹里文件删除,再删除空文件夹
function removeDir(path) {
    let data = fs.readdirSync(path) // 读取文件夹下的内容(返回一个数组)
    data.forEach(item => {
        let url = path + '/' + item // 当前路径
        let sta= fs.statSync(url)  // 当前目录/文件的详细信息
        if(sta.isFile()) { // 当前路径是文件
            fs.unlinkSync(url) // 删除
        } else { // 当前路径是文件夹
            removeDir(url) // 继续查找
        }
    })
    // 最后删除剩下的空文件夹
    fs.rmdirSync(path)
}
removeDir('22')
3.文件和目录通用的方法
(1).判断文件/目录是否存在:fs.exists() 返回true/false
fs.exists("22", res => {
    console.log(res) // true
})
(2).获取文件/目录的详细信息: fs.stat()

判断是否为文件:data.isFile()
判断是否为文件夹:data.isDirectory()
两个都是返回true/false

fs.stat('index.js', (err, data) => {
    if(err) {
        return console.log(err)
    }
    // console.log(data) // 返回一些详细信息
    // 判断是否为文件:
    // let res = data.isFile()
    // 判断是否为文件夹:
    let res = data.isDirectory()
    console.log(res)
    
})

八. buffer

buffer在nodejs里是一个类,可以当成一种数据格式, 在数据传递过程中以二进制的方式传输.

1.创建
// 方法一: new Buffer() // 6.0之前
// 方法二: Buffer.alloc()
let buffer = Buffer.alloc(10); //10字节
console.log(buffer) // 
// 方法三: Buffer.from()
let buffer = Buffer.from("大家好")
console.log(buffer)  // 
2.buffer转成字符串

xxx.toString()

let buffer = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5, 0xae, 0xb6, 0xe5, 0xa5, 0xbd])
console.log(buffer) // 
console.log(buffer.toString()) // 大家好
3.解决乱码
// 方法一:  连接 解决乱码问题
let buffer1 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5])
let buffer2 = Buffer.from([0xae, 0xb6, 0xe5, 0xa5, 0xbd])
console.log(buffer1.toString(), buffer2.toString()) // 会乱码
let buffer3 = Buffer.concat([buffer1, buffer2])
console.log(buffer3.toString()) // 大家好
// 方法二: 用node内置模块string_decoder
let {StringDecoder} = require("string_decoder")
let decoder = new StringDecoder()
let buffer1 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5])
let buffer2 = Buffer.from([0xae, 0xb6, 0xe5, 0xa5, 0xbd])
let res1 = decoder.write(buffer1)
let res2 = decoder.write(buffer2)
console.log(res1)  // 大 
console.log(res2)  // 家好

九.stream流

对于很大的文件,直接读取可能会导致内存溢出等问题,所以可以用stream流的形式,把它切割成很多个很小的块,像水流一样读取和传递.
流会把数据分成64kb的小文件里传输.

// 读取文件
const fs = require("fs")
// 原本的写法
// let res = fs.readFileSync("1.txt")
// console.log(res)
// 用stream流的方式
let res = fs.createReadStream("1.txt")
let str = ""
res.on("data", chunk => { // 读取过程中被分成好多个64kb的小块(这里相当于循环)
    str += chunk
    // console.log(chunk.toString()) // 读取到的每个小块
})
res.on("end", () => { // 流读取完成
    console.log(str) // 最终结果(所有小块的总和)
})
// 写入流
let ws = fs.createWriteSteam("2.txt");
res.pipe(ws) // 通过管道将内容一小块一小块写入到2.txt里

你可能感兴趣的:(nodejs01)