# 基础知识
官网 (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"
}