Node.js

发布于:2025-06-10 ⋅ 阅读:(23) ⋅ 点赞:(0)

1. 介绍

  • 没有DOM,BOM

  • 在node.js这个js执行环境中为js提供了一些服务器级别的操作

  • 例如文件读写

  • 网络服务的构建

  • 网络通信

  • http服务器

  • …等处理

2. 安装和使用

检查是否已经安装:

  1. 打开命令行
  2. 输入node -v或者node -version
  3. 若出现版本号,说明安装成功

编写并执行代码

  1. 在文件夹里创建js脚本文件,使用VS编写
  2. 打开终端(命令行),定位到脚本文件所属的目录(三种方法)
  • Win+R,输入cmd,然后切换到文件所在目录
  • 在文件所在地方右键->open Git bash here
  • Shift+鼠标右键,找到"在此处打开PowerShell窗口"或"在此处打开命令行窗口"
  1. 输入node 文件名,执行对应的文件

注意:文件名不可以命名为node.js,最好不用中文

01 读取文件

//1.使用require方法加载fs核心模块
//var后面的fs是变量名,可以随便起,但是括号中的'fs'不能改变
var fs =require('fs');
//2.读取文件
//  参数一是要读取文件的路径
//  参数二是一个回调函数
//    成功:
//       data:数据
//       error:错误对象
//    失败:
//       data:undefined
//       error:错误对象
fs.readFile('./data/hello.txt',function(error,data){
    console.log(data.toString());
})
fs.readFile('./data/a.txt',function(error,data){
    if(error){
        console.log("读取文件失败");
    }else{
        console.log(data.toString());

    }
})

data默认是二进制数据,可以通过.toString转换为咱们能识别的字符串或者显式指定 utf8 编码

  1. 不加utf8
 fs.readFile(dbPath, function (err, data) {
        if (err) {
            return callback(err);
        }
        console.log(data)
        console.log(typeof data);//object
        //JSON.parse() :字符串->对象
        console.log(JSON.parse(data));
        console.log(typeof JSON.parse(data)); //object
       
    })
  1. utf8

     fs.readFile(dbPath,'utf8', function (err, data) {
            if (err) {
                return callback(err);
            }
            console.log(data)
            console.log(typeof data);//String
            //JSON.parse() :字符串->对象
            console.log(JSON.parse(data));
            console.log(typeof JSON.parse(data)); //object
           
        })
    
对比项 utf8 编码(场景 1) 不加 utf8 编码(场景 2)
data 原始内容 直接显示 JSON 字符串(人类可读) 显示 Buffer 二进制对象(人类难读,如 <Buffer ...>
typeof data string(字符串类型) object(Node.js 中 Buffer 属于对象类型)
JSON.parse(data) 正常解析为 JavaScript 对象 也能解析(Node.js 自动把 Buffer 转字符串)
本质区别 主动指定编码,让 fs.readFile 返回字符串 依赖 Node.js 隐式转换,dataBuffer 对象

. JSON.parse(data) 的兼容性
  • utf8
    data 是字符串,JSON.parse(data) 直接解析为 JavaScript 对象(如 { students: [...] }),符合常规用法。

  • 不加 utf8
    JSON.parse 支持接收 Buffer 对象!Node.js 会隐式地将 Buffer 转为字符串(默认 UTF-8 解码),再解析 JSON。所以最终也能得到正确的 JavaScript 对象。

    注意:这种隐式转换是 Node.js 对 JSON.parse 的 “友好兼容”,但其他环境(如浏览器)的 JSON.parse 不支持直接传 Buffer,只认字符串。


02写文件

fs.writeFile('文件名','要写入的内容',function(err){

})
这里面打函数只有一个参数err,失败的话是错误对象,成功的话是null

03 http

可以使用node轻松地构建一个Web服务器,Node中专门提供了一个核心模块:http

  1. 最简单的http服务:
//1.http核心模块加载
var http=require('http');
//2.使用http.createSever()方法创建一个Web服务器
//返回一个Server实例
var server=http.createServer();
//3.服务器(接受请求,处理请求,给个反馈,也就是发送响应)
//当客户端请求过来,就会自动触发服务器的request请求事件,然后执行参数二,回调函数
server.on('request',function(){
console.log("收到请求了");
})
//4.绑定端口号,启动服务器
server.listen(3000,function(){
    console.log("服务器启动成功,可以通过http://127.0.0.1:3000/ 来进行访问");
})
  1. 在命令行执行Ctrl+C重启服务器,确保端口没有被占用
  2. request请求事件处理函数,需要接受两个参数
  • Request:请求对象

​ 请求对象可以用来获取客户端的一些请求信息,例如请求路径

  • Response:响应对象

​ 响应对象用来给客户端发送响应消息,响应内容只能是二进制字符串,其他的都不行

response对象有一个方法,write可以用来给客户端发送响应数据,write`可以使用很多次,但最后一定要有end来结束响应,否则客户端会一直等待

var http=require('http');
var server=http.createServer();
server.on('request',function(request,response){
    console.log("收到请求了,请求路径是"+request.url);
    // response
    response.write('hello');
    response.write('node.js');
    response.end();
    //更简单的方式:发送相应数据的同时结束响应
    response.end('helloworld');
    //以上方式不管发送什么请求,都只能响应固定的内容
})
server.listen(3000,function(){
    console.log("服务器启动成功,可以通过http://127.0.0.1:3000/ 来进行访问");
})
  1. 根据不同的请求路径相应不同的内容
var http=require('http');
var server=http.createServer();
server.on('request',function(request,response){
    //根据不同的请求路径,发送不同的响应结果
    var url=request.url;
    if(url==='/'){
        response.end('index page');
    }else if(url==='/login'){
        response.end('loginPage');
    }else if(url==='/register'){
        response.end('registerPage');
    }else{
        response.end('404 Not Found');
    }
})
//浏览器默认是80端口,输入时可以不加端口号
server.listen(80,function(){
    console.log("请求成功,可以访问了");
})

3. node中的js

  • EcmaScript

    没有BOM,DOM

  • 核心模块

  • 第三方模块

  • 用户自定义模块

1. 核心模块

Node为JavaScript提供了很多服务器级别的API.这些API绝大多数都被包装到了一个具名的核心模块中了

例如文件操作的fs核心模块,http服务构建的http模块,os操作系统的信息模块

如果说要是用一个模块,就必须有

var fs=require('fs');
var http=require('http');
var os=require('os');
  1. require是一个方法,作用是用来加载模块的

  2. 在node中,模块有三种:

    • 具名的核心模块:fs,http

    • 用户自己编写的文件模块,

      相对路径必须加 ./,不可省略

      可以省略后缀名:“js”

    console.log('a start');
    require('./b.js');
    console.log('a end');
    
  3. 在Node中,没有全局作用域,只有模块作用域,外部访问不到内部,内部访问不到外部

  4. 既然是模块作用域,那如何让模块与模块之间进行通信?

    有时候,我们加载文件模块的母的不是为了简单的执行里面的代码,而是为了使用里面的某个成员

require方法有两个作用:

  1. 加载文件模块并执行里面的代码

  2. 拿到被加载文件模块导出的接口对象

    在每个文件模块中都提供了一个对象:exports

    默认是一个空对象

    我们要做的事把所有需要被外部访问的成员挂载到exports对象中

//a.js
var bExports=require('./b.js');
console.log(bExports.foo);
console.log(bExports.add(10,5));
console.log(bExports.age);
//b.js
var foo='bbb';
exports.foo='hello';
exports.add=function(x,y){
    return x+y;
}
var age=18;
exports.age=age;

4. Node中的模块系统

使用node写应用程序主要是使用:

  • ES语言
  • 核心模块
    • 文件操作fs
    • http服务的http
    • url路径操作模块
    • path路径处理模块
    • os操作系统信息
  • 第三方模块
    • art-template
    • 必须通过npm下载才可以使用
  • 自己写的模块
    • 自己创建的文件

什么是模块化?

  1. 有文件作用域
  2. 有通信规则
    • 加载(require)
    • 导出

符合以上两点的就可以说符合模块化

CommentJS 模块规范

在node中的JS有一个重要概念:模块系统.

  • 模块作用域
  • 使用require方法来加载模块
  • 使用exports接口对象来导出模块中的成员

1. 加载require

语法:

var 自定义变量名称=require('模块');

作用:

  • 执行被加载模块中的代码
  • 得到被加载模块中的exports导出接口对象

2.导出 exports

  • Node中是模块作用域,默认文件中所有的成员只在当前文件中有效

  • 接口对象中对于希望可以被其他模块访问的成员,我们需要把这些公开的成员都挂载到 exports

    两种导出方式:

    1. 导出多个成员(必须在对象中)

      //法一:
      exports.a=123;
      exports.b='hello';
      exports.c=function(x,y){
         return x+y;
      };
      exports.d={
      foo:'bar'
      };
      //法二:
      module.exports={
         add:function(x,y){
                return x+y;
             },
         str:'hello'
      }
      
    2. 导出单各成员(拿到的就是函数,字符串)

      module.exports='hello';
      
      //以下情况会覆盖(后者会覆盖前者):
      module.exports='hello';
      module.exports=function(x,y){
      return x+y;
      }
      

3.原理解析

在Node中,每个模块内部都有一个自己的module对象,该module对象中,有一个成员叫:exports,也是一个对象

如果你需要对外导出成员,只需要把导出的成员挂载到module.exports中

var module={
  exports:{
    foo;'bar'
  }
}

在模块中,还有这么一句代码:

var exports=module.exorts;

exportsmodule.exports的一个引用

console.log(exports===module.exports);//true
exports.foo='bar';
//等价于
module.exports.foo='bar';

谁来require我,谁就得到module.exports

默认在代码的最后有一句:

return module.exports;

一定要记住,最后return的是module.exports而不是exports

当一个模块需要导出单个成员时,直接给exports赋值是不管用的,比如下面的语句就不行:

exports='hello';

原因:

示例:

var obj={};
var obj1=obj;
obj.foo='bar';
//此时obj1就是{foo:'bar'}
//继续
obj1.foo='hello';
//输出obj.foo,就是'hello'
//继续
obj1={};//这里相当于给他重新赋值了,此时obj和obj1指向的就不是一个引用了,二者的更改也不会影响到对方
obj1.foo='world';
//此时obj.foo还是hello

解释:

exports='hello'相当于给exports重新赋值了,指向另一个对象了,但是最终返回的是module.exports,所以给exports重新赋值不管用

示例:

exports.a=123;
exports={};
exports.foo='bar';
//此时导出的是{a:123}
module.exports.b=456;
//此时导出的是{a:123,b:456}

示例:

module.exports='hello';
exports.foo='bar';//这一行添加的东西没啥用,不会被导出

原因:

本来二者是一个东西,但现在给module.exports重新赋值了,他就指向另一个引用了,这时即使再给exports赋值也没有用了,因为程序最终返回的是module.exports

5. 在node中使用art-template模版引擎

  1. 安装:使用命令npm art-template

  2. 在需要使用的文件模块中加载art-template,使用require方法加载就可以了

`var template = require('art-template');`
  1. 查文档,使用模版引擎的API

    //template.render('模版字符串',替换对象);
    var template = require('art-template');
    var fs = require('fs');
    fs.readFile('./tpl.html', function (err, data) {
        if (err) {
            return console.log('读取文件失败');
        }
        // console.log(data);
        //data是二进制数据,而模版引擎的render方法需要接受的是字符串
        //需要把data转换成字符串
    // template.render('模版字符串',替换对象);
        
        var ret = template.render(data.toString(), {
            name: 'jack',
            age: 18,
            title:'个人信息'
        });
        console.log(ret);
    })
    

    模版引擎只认识{{}},不管是字符串形式的还是什么,只要里面的变量名有意义,都会被替换

tpl.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
</head>
<body>
    <p>大家好,我叫{{name}}</p>
    <p>今年{{age}}岁了</p>
    
<script>
    var foo='{{title}}';
</script>
</body>
</html>

打印ret:
在这里插入图片描述

url模块

  1. 使用:
var url=require('url');
  1. url.parse( )方法:

    var obj=url.parse('/postComment?name=我是美女&message=总结的好好',true)
    
  2. 打印obj,有一个pathname属性

    pathname: '/postComment'
    
  3. 有一个query属性

    obj.query:{ name: '我是美女', message: '总结的好好' }
    
  4. true的作用:

    将query转成对象的形式

    加之前

    'name=我是美女&message=总结的好好'
    

    加之后

    { name: '我是美女', message: '总结的好好' }
    

6. Express

1. 准备

1.1安装

//安装package.json文件
npm init -y
//安装express
npm i-S express

1.2引包

var express=require('express');

1.3创建服务应用程序,也就是 http.creatServer

var app=express();

1.4当服务器收到get请求时.执行回调处理函数,使用这种方式就不用再添加请求头了

app.get('/',function(req.res){
    res.send("找到了");
})
app.get('/about',function(req,res){
    res.send("关于我");
})

1.5端口

app.listen(3000,function(){
    console.log('qpp is running port 3000');
})

2.使用

2.1公开静态资源

法一:
app.use('/public',express.static('./public'));
这种方法可以通过/public/xxx访问public目录中的所有文件内容
法二:
app.use(express.static('./public'));
当省略第一个参数时,请求的url也要省略/public,否则访问不到

2.2在express中,可以直接使用 req.query来拿到查询字符串参数

app.get('/about',function(req,res){
//在express中可以直接使用req.query来获取查询字符串参数
console.log(req.query);
    res.send('关于我');
})

2.3基本路由:(映射关系)

  • 请求方法
  • 请求路径
  • 请求处理函数
2.3.1get:
当以get方法请求/的时候,执行对应的函数
app.get('/',function(req,res){
    res.send('Hello world');
})
在express中获取get表单数据
以前使用url.parse(req.url,true)来获取
现在直接使用req.query

2.3.2post:
当以post方法请求/的时候,执行对应的函数
app.post('/',function(req,res){
    res.send('Got a Post request');
})
在express中获取post表单数据

原方法:

安装

npm install --save body-parser

配置

var express=require('express')
//1.引包
var bodyParser=require('body-parser');
var app=express();
//配置bode-parser,只要加入这个配置,则在req请求对象上会多出来一个属性:body
//也就是可以直接通过req.body来获取post请求体数据了
app.use(bodyParser.urlencoded({extended;false}));
app.use(bodyParserr.json())

但是Express 框架本身已经内置了替代方案,无需再额外依赖 body-parser 包,具体替换方式如下:

一、核心原因

body-parser 曾是 Express 生态里常用的请求体解析中间件,但从 Express 4.16.0 及更高版本开始,框架内置了 express.json()express.urlencoded(),功能与 body-parser 完全一致,官方因此标记 body-parser 为 “弃用”(继续用也能跑,但不推荐新项目使用 )。


二、替换方法(两步搞定)
1. 移除 body-parser 相关依赖(可选但推荐)

如果你是新项目,或想彻底清理旧依赖:

  • 先卸载

    npm uninstall body-parser
    
  • 代码里删掉 require('body-parser') 的引入和相关 app.use 配置。

2. 改用 Express 内置的解析中间件

直接用 Express 自带的 express.json()express.urlencoded() 替换,示例代码:

const express = require('express');
const app = express();

// 解析 JSON 格式的请求体(替代 bodyParser.json())
app.use(express.json());  
// 解析 URL 编码的请求体(替代 bodyParser.urlencoded({ extended: ... }))
app.use(express.urlencoded({ extended: false }));  

// 后续路由可直接通过 req.body 获取参数
app.post('/your-route', (req, res) => {
  console.log(req.body); // 解析后的数据
  res.send('请求体已解析');
});

app.listen(3000, () => {
  console.log('服务器启动,端口 3000');
});

关键说明

  • express.json() 负责解析 Content-Type: application/json 的请求体(如前端传 JSON 数据);
  • express.urlencoded({ extended: false }) 负责解析 Content-Type: application/x-www-form-urlencoded 的请求体(如 HTML 表单提交);
  • extended: false 表示使用内置的查询字符串解析器(更安全、轻量),若需支持复杂嵌套对象,可设为 true(但需额外安装 qs 包 )。

只要执行了 res.redirect/res.render/res.send 中的任意一个,响应就会被 “终结”,express会自动结束相应

3.在art-template中配置express

3.1安装
npm install --save art-template
npm install --save express-art-template
3.2配置art-template模版引擎
  • 第一个参数表示,当渲染以 .art或.html结尾的文件时,使用art-template模版引擎
  • express-art-template 是专门用来在Express中把art-template整合到express中的,虽然这里不需要加载art-template,但是也必须安装,原因是express-art-template依赖了art-template
//这里写art时,则视图文件的后缀名也要改成art
//这里的art也可以改成html,这样视图文件的后缀名还保持html就可以了
app.engine('html', require('express-art-template'));
// res.render('html模版名',{模版数据})  render:渲染
3.3使用:
//找文件默认从views目录下开始找,所以要将所有的视图文件都放到views下
app.get('/', function (req, res) {
    res.render('mainPage.html', {
        comments: comments
    });
})