# 基础知识

官网 (opens new window) API 文档 (opens new window)

# 运行js代码

  • 在命令行窗口运行
  • 在VSCode终端运行
  • 不能写DOM(document)、BOM(location.href)相关的js代码


 















F:\学习\VUE\node> node 01.js

# 直接输入node,ctrl+c 执行一次换行,执行二次退出
F:\学习\VUE\node> node
Welcome to Node.js v16.14.0.
Type ".help" for more information.

# 不需要声明
> const arr = [1,2,3,4,5]
undefined
# 直接赋值
> arr = [1,2,3,4,5]
[ 1, 2, 3, 4, 5 ]
> arr.slice(1,3)
[ 2, 3 ]


# 常用内置模块

引入内置模块的方式

const fs = require("fs"); // 文件操作
const http = require("http"); // 网络操作
const path = require("path"); // 路径操作
const querystring = require("querystring"); // 查询参数解析
const url = require("url"); // URL解析
  • path:路径操作
const path = require("path");
console.log(__dirname); // 获取当前文件所在路径

let filePath = path.join(__dirname, "hello.txt"); // 拼接出完整的文件路径
  • fs:文件操作
const fs = require("fs");
const path = require("path");
let filePath = path.join(__dirname, "hello.txt");

// 同步读取数据
let content = fs.readFileSync(filePath, "utf8");
console.log(content)

// 异步读取数据
fs.readFile(filePath, "utf8", (err,data) => {
	if(err){
		console.log(err);
		return
	}
	console.log("读取到的内容为:", data);
})

// 异步写入数据,会完全覆盖原有数据
fs.writeFile(filePath, "hello node", "utf8", err => {
	if(err){
		console.log(err);
		return
	}
	console.log("写入成功!!");
})
  • http:网络操作




















 



const fs = require("fs");
const path = require("path");
const http = require("http");

const PORT = 8081; // 定义一个端口

// 创建服务器对象,处理请求
let server = http.createServer((request, response) => {
	console.log("有请求过来了!!");
	
	let filePath = path.join(__dirname, "index.html");
	let content = fs.readFileSync(filePath, "utf8");
	// 响应数据
	response.setHeader("Content-Type","text/html;charset=utf-8");
	response.write(content);
	response.end(); // 结束响应
})

// 启动服务器,并监听
server.listen(PORT, err => {
	// 服务器已启动就执行这里的代码,并且只执行一次
	console.log(`服务器已经启动了在${PORT}端口上`);
})

# 全局对象 global

global.b = 20;
console.log(this === global);// false, this并不指向全局对象

# 为什么要使用 Nodemon

# nodemon 的出现,可以随时监听文件的变更,自动重启服务,不再需要手动重启服务

# 全局安装
npm install -g nodemon

默认情况下,​​nodemon 会监视所有项目文件,啥文件改动一下都要重启服务,其实没必要

# 配置只监视 src 目录
nodemon --watch src server.js

# 配置监视文件的后缀扩展名
nodemon --ext js,json

不想用命令行模式,可以在 package.json 中的 nodemonConfig 选项中配置

"nodemonConfig": {
  "watch":["src/"],
  "ext":"js json"
}

# Base64的使用

npm install js-base64
const Base64 = require("js-base64").Base64;
Base64.encode("hello");
Base64.decode("aGVsbG8=");

# Express

Express官网 (opens new window) 作为开发框架,是目前最稳定、使用最广泛,而且 Node.js 官方推荐的唯一一个Web 开发框架。除了为 http 模块提供了更高层的接口外,还实现了许多功能,其中包括:

# 静态文件服务
# 路由控制
# 模板解析支持
# 动态视图
# 用户会话
# 错误控制器
# 插件支持

# 安装Express

  • 简单安装
npm init
npm i express --save
  • 使用 express 应用生成器安装
npm install -g express-generator
# 创建一个名为hello的Express项目
express hello
# 进入hello目录安装依赖包
npm install
# 执行命令启动应用
npm start
# 在浏览器中输入http://localhost:3000/

# 目录介绍

bin  # 启动配置文件,在www 里修改运行端口号
node_modules  # 存放所有的项目依赖库,就像java存放架包
public  # 用于存放静态资源文件 图片,CSS,JAVASCRIPT文件..
routers  # 路由文件相当于springmvc中的Controller,ssh中的action
views  # 存放页面的地方
package.json  # 项目依赖配置及开发者信息
app.js  # 应用核心配置文件,项目入口

# app.js配置详解

var createError = require('http-errors');// http错误处理模块
var express = require('express');// 引入Express
var path = require('path');// 引入path
var cookieParser = require('cookie-parser');// 引入cookie处理对象
var logger = require('morgan');// 引入日志模块
 

var indexRouter = require('./routes/index');// 引入路由目录中的index.js文件
var usersRouter = require('./routes/users');// 引入路由目录中的users.js文件

var app = express(); // 创建express应用

// view engine setup
app.set('views', path.join(__dirname, 'views')); // 定义页面目录
app.set('view engine', 'jade');// 定义页面模板引擎

app.use(logger('dev'));// 定义日志级别
app.use(express.json());// 定义json格式处理数据
app.use(express.urlencoded({ extended: false }));// 定义使用urlencode处理数据
app.use(cookieParser());// 定义使用cookie处理对象
app.use(express.static(path.join(__dirname, 'public')));// 定义静态资源目录public

app.use('/', indexRouter);// 定义指向index.js的路由
app.use('/users', usersRouter);// 定义指向users.js的路由

// 定义404错误处理
app.use(function(req, res, next) {
  next(createError(404));
});

// 定义其他错误处理
app.use(function(err, req, res, next) {
  // 设置 locals, 只在开发环境生效
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // 返回错误http状态码
  res.status(err.status || 500);
  res.render('error');// 渲染错误页面
});
module.exports = app; // 导出app

# Express路由

每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。它的使用形式如下:

app.method(path, handler)

app  # 是 express 的实例
method  # 是 HTTP 请求方法
path  # 是服务器上的路径
handler  # 是在路由匹配时执行的函数

router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

::: tips 注意 如果有多个路由处理程序,那么不是最后一个路由的情况下,其参数要有next: :::

# Express的页面

  • Express默认的模板引擎是jade,为了方便用户开发,可以把它替换成更简洁、更高效的art-template
// 安装art-template依赖包
npm install -S art-template
npm install -S express-art-template

// 修改app.js文件
app.engine('.html',requare('express-art-template')
app.set('view engine','html')
  • 将数据渲染到页面上。即调用response的render方法向页面传递数据,在页面中使用接收服务端的数据
router.get('/post',function(req,res){
  res.render('post',{
    title:'孔子学院',
    name:'张三',
    age:31,
    happy:true
  })
})
<!--前端页面-->
<p>姓名:{{name}}<br><br>年龄:{{age}}</p>
  • 条件渲染
<h2>{{title}}</h2>
<!-- 判断年龄小于30-->
{{ if age<30 }}
   <p>大家好,我是{{name}},我今年{{age}}岁,很高兴认识大家!</p>
{{ /if }}
<!-- 判断年龄大于等于30 -->
{{ if age>30 }}
   <p>大家好,我是{{name}},很高兴认识大家!</p>
{{ /if }}
  • 嵌套条件渲染
<h2>{{title}}</h2>
<!-- 判断年龄小于30-->
{{ if age<30 }}
  <p>大家好,我是{{name}},我今年{{age}}岁,很高兴认识大家!</p>
{{ /if }}

<!-- 判断年龄大于等于30 -->
{{ if age>30 }}
<p>大家好,我是{{name}}
  <!-- 判断happy字段是否为真-->
  {{ if happy }}
	<span>很高兴认识大家!</span>
  {{ /if }}
</p>
{{ /if }}
  • 循环渲染
router.get('/post',function(req,res){
  res.render('post',{
    title:'德云IT学院',
    list:[{
      id:1,
      content:'今天天气不错'
    },{
      id:2,
      content:'昨天几点睡觉的?'
    },{
      id:3,
      content:'工作好累'
    }],
    targetId:2
  });
});
<h2>{{title}}</h2>
{{ each list as item}}
  {{ if item.id === targetId}}
     <p style="color:#f00">id:{{item.id}},内容:{{item.content}}</p>
  {{ else }}
     <p>id:{{item.id}},内容:{{item.content}}</p>
  {{ /if }}
{{ /each }}

# 请求对象Request

<a href="http://localhost:8089/test/12/15">params</a>

router.get('/post/:id/:userid',function(req,res){
  res.send(req.params)
});
req.params  # 一个数组,包含所有的路由参数
req.query  # get请求的查询字符串参数
req.body  # post的请求体内容
req.cookies  # 一个对象,包含从客户端传递来的cookie信息
req.headers  # 一个对象,从客户端接到的请求抱头
req.path  # 请求路径,不包含协议,端口,查询字符串
req.host  # 主机名
req.xhr  # boolean值,判断请求是否是ajax请求
req.protocol  # 用于标示协议http,https
req.url  # path+查询字符串

# 响应对象Response

res.status(code)  # 设置http状态码,express默认是200。可利用此函数返回404或者500页面
res.send(options)  # 向客户端发送响应数据,可以是一个对象(key-value)
res.render(视图名,数据)  # 页面的文件名(不带扩展名),“数据”是向页面发送的数据
res.cookie(name,value,[options])  # 设置cookie值
res.clearCookie(name,[options])  # 清除cookie值
res.redirect([status],url)  # 重定向浏览器,默认状态码302,url是路由里面的路径不是视图里面的路径
res.json([status],json)  # 向客户端发送json数据及其可选的状态码
res.jsonp([status],jsonp)
res.send([status],body)  # 向客户端发送响应及其状态吗
res.type(type)  # 相当于res.set('Content-Type','type')

# get/post请求

  • get 请求
<form action="http://localhost:8082/login" method="get">
    用户:
    <input type="text" name="user" id="user" placeholder="用户名"/>
    <br>
    密码:
    <input type="password" name="password" id="password" placeholder="密码"/>
    <br>
    <input type="submit" value="提交"/>
</form>
// 更改router下的index.js文件(路由文件)
var express = require('express');
var router = express.Router();
 
/* GET login page. */
router.get('/', function(req, res, next) {
  res.render('login');
});

/* 获取登录页面的参数 */
router.get('/login',function(req,res){
  console.log(req.query);
  res.send("登录路由,user为:"+req.query.user+"==>   password为:"+req.query.password)
})
module.exports = router;
  • post 请求
<form action = "http://localhost:8082/add" method="POST">
	用户:<input type="text" name = "userName"> 
	<br><br>
	密码:<input type="password" name = "userPwd"> 
	<br><br>
	<button type="submit">提交</button>
</form>
//获取post页面
router.get('/post',function(req,res,next){
  res.render('post')
})
//获取post方式的请求参数
router.post('/add',(req,res)=>{
  res.send("登录路由,user为:"+req.body.userName+"==> password为:"+req.body.userPwd)
})
  • 便用body-parser获取请求参数
// 1、引入bady-parser
const bodyParser = require('body-parser')

// 2、两个配置项,bodyparser功能系加到项目app中
app.use(bodyParser.json()); // application/json 解析json格式
// application/x-www-form-urlencoded 针对普通页面提交功能
app.use(bodyParser.urlencoded({ extended: false })); // false为字符串或数组,true为任意类型

//3、在接口中获职请求参数req.body
app.post('/register’, (req, res) = {
	// 可以在回调交数中,获政请求参数(用户在页面靖写的信息)
	// 获取请求参数
	conso1e.1og(req.body);
	//获取到请求参数之后就可以在这里处理这些请求参数,比如保存到数据库中
	res.send("post ok");
})

# 操作数据库

  • 数据库连接配置
// db.js文件代码
var mysql = require("mysql")
var pool = mysql.createPool({
	host: "loaclhost",
	user: "root",
	password: "root",
	database: "user"
})
// 对数据库进行增删改查操作的基础
function query(sql, callback){
	pool.getConnection(function(err, connection){
		connection.query(sql, function(err, rows) {
			callback(err, rows)
			connection.release()
		})
	})
}

exports.query = query
  • 在项目中需要引入这个db.js之后,才能对数据库进行查询
const express = require('express');
const app= express();

// 1、引入数据库
const db = require('./db/db js"):
app.get('/'.(req, res) =>{
	// handleDb(res,"要操作的sq1指令","数据库操作失败时候的报错语句")
	let ret = await handleDb(res, "select * from students", "数据库查询失败");
	res.send(ret);
})

# jsonwebtoken的使用

npm install jsonwebtokan
  • 生成token值
const jwt = require("jsonwebtokan");
const token = jwt.sign({id:1, username:"zhangsan"}, salt, {expiresIn: 60* 60 * 2})
  • 验证token
const jwt = require("jsonwebtokan");
const token =
"gyioiJUzIINi ISInRSCI6IKpxVC39.eypzcI6mswidxNlTU4NjEYNTUMYWiZXhWI.jOXNTG2NTMNZAzfQ.WWx";
try{
	var userData = jwt.verify(token, salt); // 获股token中的数据(用户信息)
} catch(e){
	console.log("token已经过期")
}
  • 在项目中颁发token
router.post("/token",(req, res)=> {
	const token = jwt.sign({id:1, username:"zhangsan"}, salt, {expiresIn: 60* 60 * 2})
	
	//restFul风格的接口返回的数据格式
	res.json({
		errno: 0, // 错误码 0:没有错误
		errmsg: "登陆成功",
		data: {
			token,
			userInfo:{ id:1, username: "zhangsan" }
		}
	})
})

# 跨域问题处理

http://www.baidu.com:8080 地址中三者有一个不一样就会产生跨域问题

  • 使用Jsonp
// 客户端
$.ajax({
	url: "http://localhost:3000/data",
	dataType: "jsonp",
	sucess(res) {
		$(".name").html(res.name);
	}
})

// 服务端
app.get("/data", (req, res) => {
	let data = { name: "Node", age:13 };
	res.jsonp(data);
})
  • 服务端处理,设置响应头
app.get("/data", (req, res) => {
	res.setHeader("Access-Control-Allow-Orign","*");
	let data = { name: "Node", age:13 };
	res.send(data);
})
  • 服务端统一设置响应头
// npm install cors
const cors = require("cors");
const app = express();
app.use(cors());

# nodemon工具的使用

每次更改路由文件都要重新启动项目才能生效,这样开发效率不高。可以安装nodemon工具,在更改路由后就不用重新启动项目了

  • 安装nodemon工具
npm  install  -g  nodemon
  • 修改项目根目录中的package.json文件
"scripts": {
	"start": "node ./bin/www"
	// 改为
	"start": "nodemon ./bin/www"
}