相关推荐recommended
Node.js教程(想入门就来点进来看看)
作者:mmseoamin日期:2024-04-27

Node.js是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境。

Node.js主要用于编写像Web服务器一样的网络应用

官网地址:Node.js

中文官网:Node.js 中文网


前言

Node对前端的工程师来说还算是友好的,转Node.js也是相对较容易接受

如果你是一个前端程序员,你不懂得像 PHP、Python 或 Ruby 等动态编程语言,然后你想创建自己的服务,那么 Node.js 是一个非常好的选择。

Node.js 是运行在服务端的 JavaScript,如果你熟悉 Javascript,那么你将会很容易的学会 Node.js。

当然,如果你是后端程序员,想部署一些高性能的服务,那么学习 Node.js 也是一个非常好的选择。


相信你应该了解一些基本的计算机编程术语。如果你学习过 Javascript、PHP、Java 等编程语言,将有助于你更快的了解 Node.js 编程。

一、为什么要学习Node.js?

● 学习Node.js是为了解前后端交互流程

● 同时为后面学习前端框架做准备

● 前端有很多业务不能解决,需要使用Node.js处理

1.1 node的特点

  • 单线程
  • 非阻塞I/O
  • 事件驱动 event-driven

    1.2 node.js适合开发什么? 

    • 用户表单收集
    • 考试系统
    • 聊天室
    • 图文直播
    • 提供JSON的API

      二、正文 

      2.1 node下载与安装

      下载地址:Download | Node.js

      下载成功后:

      windows键+R 打开终端 输入 node -v   如果得到 Vxx.xx.xx的版本号证明安装成功

      2.2常见cmd操作

      dir–显示指定路径上所有文件或目录的信息
      md(mkdir)–建立目录
      rd(rmdir)–删除目录
      cd–进入指定目录
      copy–拷贝文件
      del–删除文件
      ren(rename)–改名。
      type–显示文本文件
      discopy–磁盘复制
      deltree–删除目录树
      mem–查看你的计算机内存有多少,以及内存的使用情况。
      chkdsk–检查你的磁盘的使用情况。
      用法: chkdsk 磁盘名
      cls–清除显示器屏幕上的内容,使DOS提示符到屏幕左上角。
      time–显示和设置DOS的系统时间
      date–显示和设置DOS的系统日期
      EXIT(exit-退出 CMD.EXE 程序(命令解释程序)。
      ver–显示正在运行的DOS系统版本号
      break -设置或清除扩展式 CTRL+C 检查。
      cacls -显示或修改文件的访问控制列表(ACL)。
      call -从另一个批处理程序调用这一个。
      chcp-显示或设置活动代码页数。
      chdir-显示当前目录的名称或将其更改。
      chkdsk-检查磁盘并显示状态报告。
      cmd- 打开另一个 Windows 命令解释程序窗口。
      color -设置默认控制台前景和背景颜色。
      comp-比较两个或两套文件的内容。
      copy-将至少一个文件复制到另一个位置。
      diskpart-显示或配置磁盘分区属性。
      doskey -编辑命令行、撤回 Windows 命令并创建宏。
      drase -删除一个或多个文件。
      FC -比较两个文件或两个文件集并显示  它们之间的不同。 
      fidn-在一个或多个文件中搜索一个文本字符串。
      • 以上是整理的部分可能用得到的指令代码

        三、node运行与顶层对象

        1.Node的运行

        在cmd工具中,使用命令

        node 文件

        代码示例

        console.log("hello world")
        

        2.顶层对象

        在浏览器 JavaScript 中,通常 window是顶层对象,而 Node.js 中的顶层对象是 global

        globalThis

        代码示例:

        console.log(this);//{} 
        console.log(global);
        console.log(globalThis);//顶级对象

        3.全局变量

        Node平台内置了例如:__filename 和 __dirname等全局变量 setInterval() setTimeout()等方法

        代码示例:

        //绝对路径
        console.log(__dirname);//盘符:\文件夹名称
        console.log(__filename);//盘符:\文件夹名称\文件名

        两者的区别:后者地址详细到当前文件 

        四、Buffer

        Buffer类是随Node.js内核一起发布的核心库

        Buffer的结构和数组很像、但Buffer就是专门用来存储二进制数据

        1.常见进制简述

        二进制、八进制、十进制、十六进制...

        二进制:0-1
        八进制:0-7
        十进制:0-9
        十六进制:0-9 A-F
        进制之间的转换:
        1、十进制转二进制
        (1)十进制转二进制的转换原理:除以2,反向取余数,直到商为0终止。
        (2)具体做法:
        将某个十进制数除2得到的整数部分保留,作为第二次除2时的被除数,得到的余数依次记下,重复上述步骤,直到整数部分为0就结束,将所有得到的余数最终逆序输出,则为该十进制对应的二进制数。
        2、十进制转八进制
        (1)转换原理:除以8,反向取余数,直到商为0终止。
        (2)具体步骤与二进制一样
        3、十进制转十六进制
        (1)转换原理:除以16,反向取余数,直到商为0终止。
        (2)具体步骤也和二进制、八进制一样,重复上述做法即可得到十六进制数。
        4、 二进制、八进制、十六进制转换为十进制
        (1) 当位数上的值超过1就要进1
        (2)当位数上的值超过7就要进1
        (3)当数位上的值超过15就要进1(0 1 2 3 4 5 6 7 8 9 A B C D E F)
        15对应的则是F,则上面可以理解为比F还大1就进1

        简单进制转换图:

        Node.js教程(想入门就来点进来看看),第1张

        2.Buffer的常见操作

        2.1基本使用

        代码案例:

        let str="hello";
        // // let str='z'
        // let s=Buffer.from(str)
        // console.log(s);
        // console.log(s.toString());

        2.2常见方法

        • from 读取

        • concat 合并缓存区

        • toString() 转换为字符串

          代码案例:

          let str1='hello';
          let str2="world";
          let b1=Buffer.from(str1)
          let b2=Buffer.from(str2)
          let b=Buffer.concat([b1,b2]);//将多个buffer合并为一个新的buffer
          // console.log(b1);
          // console.log(b2);
          console.log(b);
          console.log(b.toString());

          五、模块系统

          在Node.js中,一个js文件就称之为一个模块(Module)。

          1.模块概述

          • Node.js 的模块系统是其核心功能之一,它提供了一种方便、模块化和可重用的代码组织方式。 通过导入和导出模块,我们可以将相关功能的代码封装在一起,提高代码的可维护性和复用性。 同时,Node.js 的模块系统还具有查找规则、缓存和解决循环依赖等特性
          • 简而之就是i将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来

            2.模块的分类

            在Node中,模块分为两类:一类是Node提供的模块,称为核心模块;另一类是用户编写的模块,称为文件模块(自定义模块、第三方模块)。

            2.1 内置模块/核心模块

            例如:url querystring fs ...

            代码示例:

            //内置模块  NodeJS中自带的模块,可以直接使用
            /*
                require("模块名")
                fs/url/querystring/qs/path/http....
            */
            //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 文件模块

            文件模块常见的有:自定义模块、第三方模块

            自定义模块:

            代码示例:

            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)

            使用export和import

            • 单个导出

              • export.名称=值

            • 批量导出

              • export { 值,....}

            • 默认导出

              • export default {}

              示例:

              //单个导出
              let obj={
                  id:166,
                  name:"于晏",
                  age:18
              }
              export let age=20;
              export let name="富城"
              export let addr="相遇在街头"
              //批量导出
              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 {
              //     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
              }
              // export default {
              //     a,b,fn,arr
              // }
              //注意:一个模块只能有一个默认导出
              // export default {
              //     name:"李四"
              // }
              // 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)

              使用exports、module.exports 和require

              示例:

              //单个导出
              let name='于晏';
              let age=20;
              let addr="阳光大道";
              exports.name = '于晏';
              exports.age = 20;
              exports.addr = "阳光大道";
              let arr=[10,101,1001];
              //批量导出
              let fn = function () {
                  console.log('hello world');
              }
              let fnx = function () {
                  console.log('running........');
              }
              let arr = ['hello', 'word', 'hi'];
              let obj = {
                  no: "0001",
                  title: "鞋子",
                  price: 999
              }
              module.exports = {
                  fn: fn, fnx, arr, obj
              }
              //入口文件
              //导入
              // 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);
              2.3 模块加载机制和Commonjs简述
              • 加载核心模块,如:fs、path等,其实在node运行的时候,已经放到内存中了

              • 加上对应文件后缀,优先级为:test.js > test.json > test.node

              • 搜索路径,如果有指定路径则按照路径去找,如:require(‘./test’) 则在当前目录寻找,如果没有指定路径,则从当前目录下往上去找 node_modules文件夹,然后从文件夹里去遍历寻找对应模块名,如果找不到则到上一层node_modules去找,直到最顶层目录

              • 首次会加载比较慢,后面node.js 会将缓存相关信息到内存避免二次查询

                加载机制:

                核心模块:系统会优先加载核心模块

                自定义模块:使用时,使用相对路径(./  ../)

                第三方模块:若出现了和核心同名的模块,优先加载核心模块;没有同名,会自动检索node_modules目录

                    js--->json-->其它文件

                    

                    

                总结:尽量避免同名

                2.4 新特性

                在node的新版本中,支持使用[node:module API] 即可以使用node:前缀来标识核心模块。 

                这种方式导入包,它会绕过所需的缓存。

                区别:

                • 直接使用require('fs'),需要等node.js将所有核心模块加载完成后才可以使用,这个可以通过module.builtinModules去判断是否加载完成

                • 使用require('node:fs'),则不需要等待,可以直接调用内置模块,但是却无法使用缓存

                • // console.log(fs);
                  // const fs=require('fs')
                  // console.log(fs);
                  // const fs=require("node:fs");//加载核心模块 fs
                  // console.log(fs);
                  const url=require("node:url")
                  console.log(url);
                  const qs=require("node:querystring")

                  总结:如果是对启动速度有要求的功能,建议使用require('node:fs')模式,其他正常调用即可

                  六、包和npm

                  1.包的概念:

                  在Nodejs中包由由包结构和包描述文件两个部分组成.

                  包结构:用于组织包中的各种文件,例如:源代码文件、资源文件

                  包描述文件:描述包的相关信息,例如:package.json、bin、lib等文件

                  2.npm

                  npm是随着Nodejs一起安装的一个包管理工具,它具有以下用途:

                  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。

                  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。

                  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

                    3.npm常见命令

                    示例:

                    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
                    其它:一次性安装多个包
                    npm i 包 包 包 
                    (3)批量安装          (项目中有package.json文件)
                    npm install
                    (4)安装指定的版本
                    默认安装最新版的包
                    安装指定版本:  npm install 包名@版本号
                    查询npm服务器存在的包版本信息
                    npm  view 包名 versions 查看所有版本号
                    npm  view 包名 version 查看当前版本号
                    卸载
                    npm uninstal 包名
                    删除
                    npm rm 包名
                    其它:
                    npm config  get registry
                    npm config  set registry 地址

                    4.package.json文件详解

                    代码示例:

                    {
                      "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

                    (3) 查看当前npm的源

                    npm config get registry (查询当前的源,如果进行上面的配置后则会得到 https://registry.npm.taobao.org)

                    七、事件订阅机制

                    大多数 Node.js 核心 API 都是使用异步事件驱动架构,所以我们了解Nodejs的事件机制是很有必要的。

                    1.events模块

                    nodejs内置的模块

                    代码案例:

                    require("node:events")
                    require("events")
                    //  const e=require("node:events")
                    //   const emitter= e.EventEmitter;
                    const { EventEmitter } = require("node:events");
                    const emitter = new EventEmitter();//事件对象

                    2.常用方法

                    • on()

                    • off()

                    • once()

                    • emit() 触发事件

                    • addListener()

                    • removeListener()

                    • removeAllListener(0)

                      代码案例:

                      //  const e=require("node:events")
                      //   const emitter= e.EventEmitter;
                      const { EventEmitter } = require("node:events");
                      const emitter = new EventEmitter();//事件对象
                      //注册了一个事件
                      // emitter.on("xx",function(a,b,c,d,e,f){
                      //     console.log('xx事件运行了...');
                      //     console.log(a,b,c,d,e,f);
                      // // })
                      // emitter.on("xx", function (...a) {
                      //     console.log('xx事件运行了...');
                      //     console.log(a);
                      // })
                      // emitter.on("click", function () {
                      //     console.log('我被click了');
                      // })
                      // //注册一次性事件
                      // emitter.once('yy', function () {
                      //     console.log('一次性事件执行成功');
                      // })
                      // //解绑事件
                      // emitter.off('xx', function (...a) {
                      //     console.log('xx事件运行了...');
                      //     console.log(a);
                      // })
                      // let fn1 = function (...a) {
                      //     console.log('xx事件运行了...');
                      //     console.log(a);
                      // };
                      // let fn2 = function (...a) {
                      //     console.log('xx事件运行了...');
                      //     console.log(a);
                      // };
                      // emitter.on('xx',fn1)
                      // // emitter.off('xx',fn2)
                      // emitter.off('xx',fn1)
                      // emitter.emit("xx", 10, 20, 30, 40, 50)
                      // emitter.emit("xx", 10, 20, 30, 40, 50)
                      // emitter.emit('click')
                      // emitter.emit('click')
                      // emitter.emit('yy')
                      // emitter.emit('yy')
                      // emitter.emit('yy')
                      // console.log([]==[]);
                      // console.log(emitter);
                      //  console.log(EventEmitter);
                      emitter.addListener("mouseover",function(){
                          console.log('鼠标来了....');
                      })
                      emitter.addListener("xx",function(){
                          console.log('鼠标来了....');
                      })
                      emitter.addListener("yyy",function(){
                          console.log('鼠标来了....');
                      })
                      // emitter.removeListener()//删除
                      emitter.removeAllListeners();//删除所有
                      emitter.emit("mouseover")

                      八、文件系统

                      Nodejs内置了用于操作文件的模块:fs

                      示例:

                      require('fs')
                      require("node:fs")

                      常见的操作有文件操作、文件夹操作。

                      提供了两种操作方案:同步、异步

                      8.1文件的操作流程

                      • 打开文件 open() openSync()

                      • 写入内容 write() writeSync()

                      • 关闭文件 close() closeSync()

                        示例:

                        // const fs=require('fs');
                        const fs = require("node:fs");
                        // console.log(fs);
                        //打开文件
                        // fs.open("./dta.txt","a", function (err, fd) {
                        //     if (err) {
                        //         console.log('打开失败:', err);
                        //         return;
                        //     }
                        //     console.log('打开成功:',fd);
                        //     // let buf=Buffer.from("hello world");
                        //     fs.write(fd, "hello world", function (err) {
                        //         if (err) {
                        //             console.log("写入失败:", err);
                        //             return
                        //         }
                        //         console.log("写入成功");
                        //         fs.close(fd,function(err){
                        //             if(err){
                        //                 console.log('关闭失败:');
                        //                 return 
                        //             }
                        //             console.log('关闭成功');
                        //         })
                        //     })    
                        // })
                        //同步
                        try {
                            let fd = fs.openSync("./data.txt", "w")
                            fs.writeSync(5, "Hello,同步方式");
                            fs.closeSync(fd);
                        } catch (e) {
                            console.log("发生异常,请稍后重试");
                        }
                        // let fd=fs.openSync("./data.txt","w");
                        // // let fd=fs.openSync(`${__dirname}/data.txt`);
                        // fs.writeSync(fd,"hello")
                        // fs.close();

                        8.2文件操作

                        常见的方法:

                        • readFile()

                        • writeFile()

                        • rename()

                        • unlink()

                          注意:每个方法都有对应的同步方法

                          示例:

                          /*
                              readFile()  读取
                              writeFile()  写入
                              rename()     重命名/剪切
                              unlink()     删除文件
                          */
                          const fs=require('fs');
                          //注意:若文件不存在,则会先创建文件,再写入(不会创建文件夹)
                          fs.writeFile("./info/info.txt","我好",err=>{
                              if(err){
                                  console.log('写入失败:',err);
                                  return;
                              }
                              console.log("写入成功");
                          })
                          // fs.writeFile("./data.txt","写入的内容",{flag:"a"},err=>{   
                          //     if(err){
                          //         console.log('写入失败:',err);
                          //         return;
                          //     }
                          //     console.log("写入成功");
                          // })
                          // fs.writeFileSync("./data.txt","hello jack",{flag:"a"})
                          //剪切
                          // fs.rename("./msg.txt","../data.txt",err=>{
                          //     if(err){
                          //         console.log('写入失败:',err);
                          //         return
                          //     }
                          //     console.log('成功');
                          // })
                          // fs.renameSync("../data.txt","./data.txt")
                          // console.log('成功');
                          //删除文件
                          // fs.unlink('./dat.txt',err=>{
                          //     if(err){
                          //         console.log('失败',err);
                          //         return
                          //     }
                          //     console.log('成功');
                          // })
                          // fs.unlinkSync("./dta.txt")
                          //读取文件
                          // fs.readFile("./data.txt",(err,data)=>{
                          //     if(err){
                          //         console.log('读取失败:',err);
                          //         return;
                          //     }
                          //     // console.log(data);//Buffer
                          //     console.log(data.toString());
                          // })
                          // let buf=fs.readFileSync("./1.html")
                          // let buf=fs.readFileSync("./data/1.wmv")
                          // console.log("读取成功");
                          // console.log(buf);
                          // console.log(buf.toString());//非文本类型文件,不可以toString()
                          

                          8.3 文件夹操作

                          常见方法:

                          • mkdir()

                          • rmdir()

                          • readdir()

                          • stat() 读取文件的信息

                            • stats对象

                              • isDirectory() 是否为文件夹

                              • isFile() 是否为文件

                            示例代码:

                            /*
                                文件夹操作
                                mkdir()
                                readdir()
                                rmdir()
                            */
                            const fs=require("fs");
                            //创建文件夹
                            // fs.mkdir("./mock",err=>{
                            //     if(!err){
                            //         console.log('成功');
                            //         return
                            //     }
                            //     console.log('失败:',err);
                            // })
                            // fs.mkdirSync("./route")
                            //读取目录
                            // fs.readdir("./data",(err,files)=>{
                            //     if(err){
                            //         console.log("失败;",err);
                            //         return
                            //     }
                            //     console.log(files);
                            // })
                            // let files=fs.readdirSync("./data")
                            // console.log(files);
                            //删除
                            // //删除空目录
                            // fs.rmdir("./data",err=>{
                            //     if(err){
                            //         console.log('失败',err);
                            //         return
                            //     }
                            //     console.log('成功');
                            // })
                            

                            8.4 流(了解即可)