Node基本使用

1. 创建自定义全局指令

1.1 新建一个空的文件夹, 创建一个cli.js文件

1.2 在cli.js写入内容

/usr/bin/env就是让系统使用node来执行你的脚本文件。

复制代码
#! /usr/bin/env node

1.3 执行终端指令

复制代码
// 在文件夹 node-project 的终端下执行指令

npm init

执行完后package.json结构如下, 其中aaa是创建指令时package name

命令完成后,在你的终端输入bin下面的属性值,比如我就应该输入aaa

如上图, 这时候就会输出aaa。如果你能正确的输出内容,那么你的全局自定义命令就创建好了。

2. 使用commander指令

2.1 处理help选项(option)

复制代码
#! /usr/bin/env node

// 按照commander
npm i commander

// 在cli.js内使用
const {program} = require('commander')

// 使用aaa --help后, Option选项将会添加下方配置, 效果图如下图
program.option('-f --framwork <framwork>', '设置框架')

program.parse(process.argv)

2.2 自定义命令参数处理(command)

复制代码
#! /usr/bin/env node

// 按照commander
npm i commander

// 在cli.js内使用
const {program} = require('commander')


// 需要自定义创建aaa create xxx a b c d指令时, 需要使用command
// 使用aaa --help后, Command选项将会添加下方配置, 效果图如下图
program.command('create <project> [other...]')
.alias('crt') // 给create起别名
.description('创建项目') // 描述
.action((project, args) => {
    console.log(project) // xxx
    console.log(args) [a, b, c, d]
}) // 业务逻辑

program.parse(process.argv)

2.3 对上方代码进行模块拆分

复制代码
// cli.js

#! /usr/bin/env node
const {program} = require('commander')

// 对模块进行拆分

// 导入help.js
const help = require('../lib/core/help')
help(program)

// 导入commander.js
const commander = require('../lib/core/commander')
commander(program)

program.parse(process.argv)


// action.js

const myAction = (project, args) => {
     // 命令行的执行逻辑代码
     console.log(project, args);
}

module.exports = myAction

// commander.js

const myAction = require('./action')

const commander = (program) => {
    // 需要创建create指令时需要使用command函数, 然后控制台可以打印 aaa create xxx k g x d
    program.command('create <project> [other...]')
    // 给create起别名
    .alias('crt')
    // 描述
    .description('创建项目')
    // 业务逻辑
    .action(myAction)
}

module.exports = commander

// help.js

const help = (program) => {
    return program.option('-f --framwork <framwork>', '设置框架')
}

module.exports = help

2.4. 命令行问答交互: 使用 inquirer 库

复制代码
// 安装 inquirer 8及以下版本用法
npm install --save inquirer@^8.0.0

// config.js
module.exports = {
    framework: ['express', 'koa', 'egg']
}

// action.js
const inquirer = require('inquirer')
const config = require('../../config')

const myAction = (project, args) => {
     // 命令行的执行逻辑代码
     inquirer.prompt([
        {
            type: 'list',
            name: 'framework',
            choices: config.framework,
            message: '请选择框架'
        }
     ]).then(answer => {
        // 用户回答的内容
        console.log(answer);
        
     })
}

module.exports = myAction



// 安装 inquirer 9及以上版本用法
npm install --save inquirer

// config.js
module.exports = {
    // framework: [
    //     {
    //         name: 'express',
    //         value: '选项一'
    //     },
    //     {
    //         name: 'koa',
    //         value: '选项二'
    //     },
    //     {
    //         name: 'egg',
    //         value: '选项三'
    //     }
    // ],
    framework: ['express', 'koa', 'egg'] // 和上面那种写法一样
}

// action.js
const inquirer = require('inquirer').default
const config = require('../../config')

const myAction = (project, args) => {
     // 命令行的执行逻辑代码
     inquirer.prompt([
        {
            type: 'list',
            name: 'framework',
            message: '请选择框架',
            choices: config.framework
        }
     ]).then(answer => {
        // 用户回答的内容
        console.log(answer);
        
     })
}

module.exports = myAction

2.5. download-git-repo: 下载原创仓库模块代码

复制代码
// 安装
npm i download-git-repo


// action.js
const inquirer = require('inquirer').default
const downloadFn = require('./download')
const config = require('../../config')

const myAction = async (project, args) => {
    // project 是项目名字

     // 命令行的执行逻辑代码
     const answer = await inquirer.prompt([
        {
            type: 'list',
            name: 'framework',
            message: '请选择框架',
            choices: config.framework
        }
     ])

    // 用户回答的内容
    downloadFn(config.frameworkUrl[answer.framework], project)

}

module.exports = myAction



// download.js
const download = require('download-git-repo')
const config = require('../../config')

const downloadFn = (url, project) => {
    /**
     * 
     * 第一个参数: direct: 我们的仓库不在他默认的仓库下, 所以需要设置一个前缀, 后面再跟上你的仓库地址
     * 第二个参数: 指定下载的路径
     * 第三个参数: 以什么样的方式下载(clone: 以克隆方式下载)
     * 第四个参数: 错误提示
     */
    download(`direct:${url}`, project, {clone: true}, err => {
        console.log(err);
        
    })
}

module.exports = downloadFn

2.5. ora: 下载等待提示交互

复制代码
// 安装(6及以上使用import, commonjs要6以下)
npm i ora@5

// download.js
const download = require('download-git-repo')
const ora = require('ora')

const downloadFn = (url, project) => {
    const spinner = ora().start()
    spinner.text = '代码正在下载...'

    /**
     * 
     * 第一个参数: direct: 我们的仓库不在他默认的仓库下, 所以需要设置一个前缀, 后面再跟上你的仓库地址
     * 第二个参数: 指定下载的路径
     * 第三个参数: 以什么样的方式下载(clone: 以克隆方式下载)
     * 第四个参数: 错误提示
     */
    download(`direct:${url}`, project, {clone: true}, err => {
        if(!err) {
            spinner.succeed('下载成功')
            console.log('Done! you run:');
            console.log('cd' + project);
            console.log('npm install');
            console.log('npm run dev');
            
        } else {
            spinner.fail('下载失败')
        }
    })
}

module.exports = downloadFn

2.6. chalk: 命令行样式输出

复制代码
// 安装, 5及以上版本使用import, 4及以下使用commonjs
npm i chalk@4


// download.js
const download = require('download-git-repo')
const ora = require('ora')
const chalk = require('chalk')

const downloadFn = (url, project) => {
    const spinner = ora().start()
    spinner.text = '代码正在下载...'

    /**
     * 
     * 第一个参数: direct: 我们的仓库不在他默认的仓库下, 所以需要设置一个前缀, 后面再跟上你的仓库地址
     * 第二个参数: 指定下载的路径
     * 第三个参数: 以什么样的方式下载(clone: 以克隆方式下载)
     * 第四个参数: 错误提示
     */
    download(`direct:${url}`, project, {clone: true}, err => {
        if(!err) {
            spinner.succeed('下载成功')
            console.log(chalk.green('Done! you run:'));
            console.log(chalk.green('cd' + project));
            console.log(chalk.green('npm install'));
            console.log(chalk.green('npm run dev'));
            
        } else {
            spinner.fail('下载失败')
            console.log(chalk.red.bold('失败的颜色'));
        }
    })
}

module.exports = downloadFn

3. Web服务器项目开发

3.1 使用node创建HTTP服务器

复制代码
// server.js

// nodemon 检测代码更改, 一旦有代码改变就会重新运行 npm i -g nodemon
// nodemon server.js

// 导入http模块
const http = require('http')

// 创建服务器
// 获取到服务器的实例对象
const server = http.createServer()

server.listen(3030, () => {
    console.log('http://127.0.0.1:3030');
    
    console.log('创建成功');
})

// 监听客户端信息
server.on('request', (req, res) => {
    res.write('哈哈')
    res.end()
})

3.2 服务器响应不同数据类型

复制代码
// nodemon 检测代码更改, 一旦有代码改变就会重新运行 npm i -g nodemon
// nodemon server.js

// 导入http模块
const http = require('http')

const fs = require('fs')

// 创建服务器
// 获取到服务器的实例对象
const server = http.createServer()

server.listen(3030, () => {
    console.log('http://127.0.0.1:3030');
    
    console.log('创建成功');
})

// 监听客户端信息
server.on('request', (req, res) => {
    // 第一种发送内容方式
    // res.setHeader('Content-Type', 'text/plain;charset=utf-8') // 例子:哈哈
    // res.setHeader('Content-Type', 'text/html;charset=utf-8') // 例子: <div>哈哈</div>
    // res.write('哈哈')
    // res.end()


    // 第二种发送内容方式
    console.log(req.url, 'req');
    
    if (req.url === '/') {
        // 如果路径是当前地址
        fs.readFile('./index.html', 'utf-8', (err, data) => {
            res.write(data)
            res.end()
        })
    } else {
        // 处理其他图片等静态文件
        fs.readFile('./1.jpg', (err, data) => {
            res.end(data)
        })
    }
})



// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>我是HTML的文件的div内容</div>
    <img src="./1.jpg">
    <img src="./1.jpg">
</body>
</html>

3.3 HTTP的不同请求方法处理(http方法和响应码)

3.4 接收并处理GET和POST请求入参

复制代码
// GET 和 POST

// 导入http模块
const http = require('http')

const fs = require('fs')
const url = require('url')

// 创建服务器
// 获取到服务器的实例对象
const server = http.createServer()

server.listen(3030, () => {
    console.log('http://127.0.0.1:3030');
    console.log('创建成功');
})

// 监听客户端信息
server.on('request', (req, res) => {
    // GET请求url后的参数获取
    if (req.method === 'GET') {
        // url.parse第一个参数是地址, 第二个参数设置成true时返回参query会把路径后面的参数转成对象形式, 比如路径是localhost:3000/user?id=100, 那么query的值是{id: 100}
        const id = url.parse(req.url, true).query.id // 获取GET请求url后的参数
        console.log(url.parse(req.url, true).query);
        
        if (req.url === '/') {
            // 如果路径是当前地址
            fs.readFile('./index.html', 'utf-8', (err, data) => {
                res.write(data)
                res.end()
            })
        } else {
            // 处理其他图片等静态文件
            fs.readFile('./1.jpg', (err, data) => {
                res.end(data)
            })
        }
    } else if (req.method === 'POST') {
        let data = '';
        // 绑定data事件, 每当有数据的时候都会触发
        req.on('data', _data => {
            // 每当客户端发送数据过来的时候就存到data上
            data += _data // _data是Buffer, 里面是二进制数据
        })

        // 所有数据都发完之后触发事件
        req.on('end', () => {
            // 对数据进行转换
            const dataString = require('querystring').parse(data);
            console.log(dataString);
            res.end()
            
        })
    }
})

3.5 服务器代码模块化拆分

复制代码
// server.js

// 导入http模块
const http = require('http')

const router = require('./router')

// 创建服务器
// 获取到服务器的实例对象
const server = http.createServer()

server.listen(3030, () => {
    console.log('http://127.0.0.1:3030');
    console.log('创建成功');
})

// 监听客户端信息
server.on('request', (req, res) => {
    router(req, res)
})



// router.js

const fs = require('fs')
const url = require('url')
const controller = require('./controller')

module.exports = (req, res) => {
    // GET请求url后的参数获取
    if (req.method === 'GET') {
        // url.parse第一个参数是地址, 第二个参数设置成true时返回参query会把路径后面的参数转成对象形式, 比如路径是localhost:3000/user?id=100, 那么query的值是{id: 100}
        const id = url.parse(req.url, true).query.id // 获取GET请求url后的参数
        console.log(url.parse(req.url, true).query);
        
        if (req.url === '/') {
            // 业务逻辑处理: 处理主页的内容
            controller.index(res)
        } else {
            // 处理其他图片等静态文件
            fs.readFile('./1.jpg', (err, data) => {
                res.end(data)
            })
        }
    } else if (req.method === 'POST') {
        let data = '';
        // 绑定data事件, 每当有数据的时候都会触发
        req.on('data', _data => {
            // 每当客户端发送数据过来的时候就存到data上
            data += _data // _data是Buffer, 里面是二进制数据
        })

        // 所有数据都发完之后触发事件
        req.on('end', () => {
            // 对数据进行转换
            const dataString = require('querystring').parse(data);

            // 业务逻辑处理: 处理用户数据信息
            controller.user(dataString, res)
            
        })

        res.end()
    }
}


// controller.js

const fs = require('fs')

module.exports = {
    index(res) {
        // 处理主页信息的返回
        fs.readFile('./index.html', 'utf-8', (err, data) => {
            res.write(data)
            res.end()
        })
    },
    user (data, res) {
        // 处理用户数据信息
        console.log(data);
        
    }
}

4. Express框架

4.1 项目构建和使用及管理用户数据信息(GET和POST)

复制代码
// 初始化项目, 先创建express-fm文件夹, 然后打开这个文件夹的终端, 执行下面指令
npm init -y
npm i express

// 创建express脚手架工具, 使用下面指令
npx express-generator
npm i


// app.js
const express = require('express')
const fs = require('fs')
const {promisify} = require('util')

// 对fs.readFile进行Promise化
const readFile = promisify(fs.readFile)

// 获取express全局应用
const app = express();

// 接收到客户端发送过来的类型数据
app.use(express.urlencoded()) // 用于接收x-www-form-urlencodeed
app.use(express.json()) // 用于接收json

// 监听get请求, 第一个参数是请求路径为/, 
app.get('/', async (req, res) => {
    // 读取db.json文件
    try {
        const data =  await readFile('./db.json', 'utf8')
        console.log(res);
        
        // 如果没报错, 发送数据
        // 对data数据进行整理, 只需要返回 users 的数据
        const back = JSON.parse(data)
        res.send(back.users)
    } catch (error) {
        res.status(500).json({error})
    }
})

// 监听POST请求, 第一个参数是请求路径为/, 
app.post('/', (req, res) => {
    // 获取客户端不同类型入参
    console.log(req.body); // 必须使用app.use对数据类型进行处理
    
})

// 对服务器进行监听
app.listen(3030, () => {
    console.log('Run http://127.0.0.1:3030');
    
})

4.2 添加用户信息到db.json文件(对文件进行读取(get)和写入(post))

复制代码
// 对文件进行读取和写入项目
// GET请求: http://127.1.1.0:3030
// POST请求: http://127.1.1.0:3030, 格式json: {"username": "hony","age": 12}


// app.js 
const express = require('express')
const db = require('./db')

// 获取express全局应用
const app = express();

// 接收到客户端发送过来的类型数据
app.use(express.urlencoded()) // 用于接收x-www-form-urlencodeed
app.use(express.json()) // 用于接收json

// 监听get请求, 第一个参数是请求路径为/, 
app.get('/', async (req, res) => {
    // 读取db.json文件
    try {
        const data =  await db.getDb()
        // 如果没报错, 发送数据
        // 对data数据进行整理, 只需要返回 users 的数据
        res.send(data.users)
    } catch (error) {
        res.status(500).json({error})
    }
})

// 监听POST请求, 第一个参数是请求路径为/, 
app.post('/', async (req, res) => {
    // 获取客户端不同类型入参
    const body = req.body;
    if (!body) {
        res.status(403).json({error: '缺少客户信息'})
    }

    // 添加
    const dataObj =  await db.getDb()
    body.id = dataObj.users[dataObj.users.length - 1].id + 1;

    dataObj.users.push(body)
    // 对db.json数据进行添加, 使用文件写入
    try {
        const r = await db.serveDb(dataObj)
        if (!r) {
            // 写入成功时, r的值为undefined, 给一个响应为200
            res.status(200).send({code: 8, msg: '添加成功'})
        } else {
            // 有错误的情况
        }
    } catch (error) {
        res.status(500).json({error})
    }
})

// 对服务器进行监听
app.listen(3030, () => {
    console.log('Run http://127.0.0.1:3030');
    
})


// db.js
// 该文件用户读取文件和写入操作

const fs = require('fs')
const {promisify} = require('util')

// 对fs.readFile进行Promise化
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)

exports.getDb = async () => {
    const data =  await readFile('./db.json', 'utf8')
    return JSON.parse(data);
}

exports.serveDb = async (data) => {
    const stringData = JSON.stringify(data)
    return await writeFile('./db.json', stringData)
}





// db.json

{
    "users": [
        {
            "username": "Li Lei",
            "age": 18,
            "id": 1
        }
    ]
}

4.3 修改用户信息(PUT)

复制代码
// app.js

const express = require('express')
const db = require('./db')

// 获取express全局应用
const app = express();

// 接收到客户端发送过来的类型数据
app.use(express.urlencoded()) // 用于接收x-www-form-urlencodeed
app.use(express.json()) // 用于接收json


// 修改用户信息
app.put('/:id', async (req, res) => {
    let id = req.params.id; // 获取url后面的参数id值
    const body = req.body; // 获取到body数据 这里使用的是json格式的
    id = Number.parseInt(id);

    try {
        const userInfo = await db.getDb();
        const user = userInfo.find(item => item.id === id)
        if (!user) {
            // 如果用户不存在
            res.status(403).json({error: '用户信息不存在'})
        }
        // 存在则替换
        user.username = body.username ? body.username : user.username // 客户端可以传username也可以不传
        user.age = body.age ? body.age : user.age // 客户端可以传age也可以不传
        
        // 替换userInfo内对应的id内容
        userInfo.forEach(item => {
            if (item.id === id) {
                item.username = user.username
                item.age = user.age
            }
        });

        // 然后写入操作
        const r = await db.serveDb(userInfo)
        
        if (!r) {
            res.status(201).json({msg: '修改成功'})
        }

    } catch (error) {
        res.status(500).json({error})
    }
})

// 对服务器进行监听
app.listen(3030, () => {
    console.log('Run http://127.0.0.1:3030');
    
})

5. MongoDB数据库进行数据持久化存储

5.1 在不同操作系统中安装MongoDB(偶数稳定版, 基数测试版)

复制代码
1

3. fs读写模块

复制代码
const fs = require('fs')

// // 读取文件内容
fs.readFile('./a.txt', 'utf8', (err, data) => {
    console.log(err);
    console.log(data);
})

// // 写入文件内容
fs.writeFile('./a.txt', 'aaaaaaa', (e) => {
    console.log(e);
})

// 追加文件内容
fs.readFile('./a.txt', 'utf8', (e, data) => {
    if (!e) {
        const newData = `${data}???`;
        fs.writeFile('./a.txt', newData, e => {
            if (!e) {
                console.log('追加内容成功啦');
                
            }
        })
    }
})

fs

1111

相关推荐
寅时码3 小时前
从“一键部署”到“可观测、可定制的发布流”:我如何打造一个企业级部署工具
运维·开源·node.js
这是个栗子3 小时前
【Node.js安装注意事项】-安装路径不能有空格
前端·npm·node.js
chancygcx_4 小时前
前端核心技术Node.js(二)——path模块、HTTP与模块化
前端·http·node.js
丘色果4 小时前
NPM打包时,报reason: getaddrinfo ENOTFOUND registry.nlark.com
前端·npm·node.js
自学也学好编程7 小时前
【BUG】nvm无法安装低版本Node.js:The system cannot find the file specified解决方案
node.js·bug
牧码岛7 小时前
服务端之nestJS常用异常类及封装自定义响应模块
node.js·nestjs
奕辰杰12 小时前
关于npm前端项目编译时栈溢出 Maximum call stack size exceeded的处理方案
前端·npm·node.js
yzzzzzzzzzzzzzzzzz1 天前
node.js之Koa框架
node.js
Java陈序员1 天前
轻松设计 Logo!一款 Pornhub 风格的 Logo 在线生成器!
vue.js·node.js·vite
gongzemin1 天前
使用Node.js开发微信第三方平台后台
微信小程序·node.js·express