# Node.js
Node.js是一个javascript的运行环境,不是一个框架或者一个库,是一个软件。
# 1. 全局对象
node下的全局对象global
//console.log(global) ==> node引擎下的全局对象
let a = 10;
console.log(global.a)
//解释文件(js文件)的模式下,a不会被挂载到全局对象上。
//交互模式(黑窗口的命令行)下,定义的变量会被挂载到global上。
global.b=20
console.log(b) //挂载在global上的变量可以直接访问
console.log(global === this); //false 解释文件模式下,this不指向global,而是指向本模块(该js文件);但是在交互模式下,this指向global。
# 2. 模块的使用
# 使用模块的好处(了解)
- 最大的好处就是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。
- 使用模块可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己编写模块时,不必考虑名字会与其他模块冲突。
# 模块规范的定义(了解)
- 一个js文件就是一个模块,模块的作用域时私有的,内部定义的变量或者函数,只在当前的文件(模块)可以使用。
- 如果别人使用我们模块里面的的东西,那么有两点要做:(以commonJS的Modules规范:Node.js为例)
- 自己编写的模块,由于模块作用域是私有的,默认情况下,外部是没有办法使用的。可以导出exports或者modules.exports。导出的时候以对象的方式导出。
- 别人要使用,则需要先引入该模块,使用require引入,并设置一个变量来接收导入的对象。
对书写格式和交互规则的详细描述,就是模块定义规范。
- AMD规范:Require.js 【模块化规范的鼻祖,旧规范,已经退出历史舞台了】
- CMD规范:Sea.js 【模块化规范的鼻祖,旧模范,已经退出历史舞台了】
- CommonJS的Modules规范:Nodejs【现在正在使用的】
- ES6模块化规范 import ... from ...【现在正在使用的】
# 模块化使用
# commonJS的使用
CommonJS的Modules规范,也是Nodejs自带的规范,就是规范了导出该怎么写,导入该怎么写
//CommonJS模块规范
let a=10;
function fn(){
console.log('我是模块中的函数fn')
}
class Animal{
constructor(){
this.age=0
}
}
//CommonJS导出的第一种格式
exports.a=a
exports.fn=fn
exports.Animal=Animal
//CommonJS导出的第二种格式
module.exports = {
a,
fn,
Animal
}
//引入模块
const xxx(跟模块文件名一致) = require('./modules/xxx.js');
//使用
console.log(xxx.a) //10
xxx.fn() //我是模块中的函数fn
let ani = new xxx.Animal();
console.log(an1.age)
/*
注意:
1.require() 是commonJS引入模块的一个方法
2.引入模块之后,被一个常量接收,常量名一般跟模块名一致(不是必须,但大家都这么做)
3.当导入的是js文件时,后缀名可以不写
4.如果文件名是index.js,则整个文件名都可以不写
*/
# 模块中的this指向
//模块中的this指向本模块
console.log(exports); //{}
console.log(module.exports) //{}
console.log(exports===module.exports) //true
console.log(exports===this) //true
console.log(this) //{}
console.log(global===this) //false
# 3. node常用内置模块
一般项目中模块分为3种:
- node内置模块
- 自己书写的模块
- 第三方模块(使用一个专门的工具npm进行统一管理)
常见的内置模块
- fs :操作文件
- http :网络操作
- path :路径操作
- querystring :查询参数解析
- url :url解析
const fs = require('fs');
const http = require('http');
const path = require('path');
const qs = require('querystring');
const url = require('url');
nodejs内置模块的文档网址:http://nodejs.cn/api/
# 4. path内置模块
//引入path模块
const path = require('path');
//跟path无关,但使用path时会用到
console.log(__dirname) //可以获取到该js文件所在的路径
//通过拼接的方式:获取当前文件的确完整路径
let filepath = path.join(__dirname,'文件名')
//第一个参数:获取当前文件所在位置
//当前文件的文件名
//获取同级其他目录下的文件路径
let filepath2 = path.join(__dirname,'文件夹名','文件名')
# 5. fs文件模块
# 同步读取
//同步读取
const fs = require('fs');
const path = require('path');
//获取被读取文件的路径
let filepath = path.join(__dirname, 'demo02.txt');
let ret = fs.readFileSync(filepath,'utf-8');
console.log(ret); //<Buffer e8 8b 8f e4 b8 9c e6 97 ad> 是node引擎存储文件数据的一种格式,以十六进制的方式存储
//通过toString()转成字符串就是我们能看懂的信息了
console.log(ret.toString()); //苏东旭
//同步sync:任务按顺序执行,执行完一个任务后再去执行另外一个任务
//异步async:有回调函数的几乎都是异步。如ajax请求、事件、定时器
# 异步读取
//异步读取
const fs = require('fs');
const path = require('path');
//获取被读取文件的路径
let filepath = path.join(__dirname, 'demo02.txt');
fs.readFile(filepath,'utf-8',(err,data)=>{
//err 错误
//data 读取到的数据
if(err){
console.log(err);
return;
}
console.log(data)
});
# 异步写入
//会覆盖原来的内容,追加appendFile
const fs = require('fs');
const path = require('path');
let filepath = path.join(__dirname, 'demo02.txt');
fs.writeFile(filepath,'hello world!','utf-8',err => {
if(err){
console.log(err);
return;
}
console.log('写完了!')
})
# 服务器搭建
使用 http 模块 搭建服务器
//1.引入http模块
const http = require('http');
//2.使用http模块搭建一个http服务器
let server = http.createServer((req,res)=>{
//req:请求报文,所有和请求有关的都在req中
//res:响应报文,所有和响应有关的都在res中
//获取请求方式
let method = req.method;
//获取请求路径(端口号后面的)
let reqUrl = req.url;
console.log('this is server');
//告诉客户端,服务端的响应结束了
//设置响应体
res.write("<h1>this is server title </h1>")
res.end());
})
//3.设置监听端口
server.listen(8090);
//简写
let http = require('http');
http.createServer((req,res)=>{
res.end('Hello World')
}).listen(3000)
# url模块
解析路径中的参数
//引入url模块
const url = require('url');
//url模块的parse()方法可以解析请求路径中的参数【写在服务器的箭头函数中】
let server = http.createServer((req,res)=>{
let param = url.parse('请求路径',布尔类型);
let 变量 = param.query.属性名;
})
/*
参数
请求路径:req.url
布尔类型:true 解析后的结果中query就是对象格式
false 解析后的结果中query就是字符串格式
*/
# 文件系统模块
加载静态资源
//引入fs模块
const fs = require('fs');
if(url == "/路径" && req.method == "请求方式"){
//fs模块的readFile()方法可以异步读取文件【写在服务器的箭头函数中】
fs.readFile('要加载的静态资源名',(err,data)=>{
//err:错误优先机制,回调函数的第一个参数为错误信息
//data:已经加载的静态资源,如果data获得的是文件内容的二进制数据,若想获得原字符串内容要加toString()方法
if(err){
res.write('404')
}else{
res.write(data)
//res.write(data.toString())
}
})
}else{
let u = '.'+url;
fs.readFile(u,(err,data)=>{ })
}
使用addListener监听表单中的数据
if(url == "/路径" && req.method == "POST"){
let 变量 = "";
//监听表单数据
req.addListener("data",chunk=>{
//chunk存储的就是每一次监听到的数据
//我们需要把每一次监听到的内容存储起来
变量+=chunk;
})
//返回监听结果
req.addListener("end",()=>{
//处理我们监听到的数据 ,得到的就是查询字符串
//xxx=xxx&xxx=xxx
})
}
使用解析查询字符串模块 ==> 就是把查询字符串转换成对象格式
//引入querystring模块
const qs = require('querystring')
let param = qs.parse(要解析的字符串)
//username=admin&pass=123123 => {usernme:admin,pass:123123}
# formidable模块
接收表单数据
//该模块不是nodejs内置模块,需要手动下载
const form = require('formidable');
//判断表单提交
if(url == "/路径" && req.method == "POST"){
//1.实例化
let 变量 = new form.IncomingForm();
//2.设置文件上传路径(将本地文件上传到服务器的哪个文件夹)
变量.uploadDir='./xxxx';
//3.设置是否保留文件的扩展名,默认是false
变量.keepExtensions = true;
//4.解析
变量.parse(req,(err,fields,files)={
// err 错误信息
// fields 普通字段信息(接收表单中的信息)
// files 上传文件的详细信息
console.log(fields);
console.log(files);
res.end()
})
}
//如果是上传文件,需要在html的form标签中添加属性:enctype='multipart/form'
# 数据库
# 数据库的使用
const http = require('http');
//引入mysql模块
const mysql = require('mysql');
//配置数据库
let connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'rootroot',
database:'数据库名'
})
//连接数据库
connection.connect()
let server = http.createServer((req,res)=>{
let url = req.url;
if(url == '/路径' && req.method == 'GET'){
let sql = 'sql语句';
connection.query(sql,(error,results)=>{
//query(参数1,参数2)
//参数1:sql语句
//参数2:回调函数 ==> error错误信息,results返回结果
if(!error){
console.log(results);
res.end()
}
})
}
})
server.listen(8090)
# 数据库预解析
防止sql注入
const http = require('http');
//引入mysql模块
const mysql = require('mysql');
//配置数据库
let connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'rootroot',
database:'数据库名'
})
//连接数据库
connection.connect()
let server = http.createServer((req,res)=>{
let url = req.url;
if(url == '/路径' && req.method == 'GET'){
//准备sql
let sql = 'select * from sql where id = ?';
//绑定值【必须是数组!!!】
let val = [10];
//返回预处理
let newSql = mysql.format(sql,val);
connection.query(newSql,(error,results)=>{
if(!error){
////affectedRows: 1, 受影响行数
console.log(results);
res.end()
}
})
}
})
server.listen(8090)
# Express框架
是Node.js官方推荐的唯一一个Web开发框架。
- 静态文件服务
- 路由控制
- 模版解析支持
- 动态视图
- 用户会话
- 错误控制器
- 插件支持
官网:http://www.expressjs.com.cn
express是一个基于内置核心http模块的,一个第三方的包,专注于web服务器的构建。
//Express不是内置模块需要下载
// 1. 引入express模块
const express = require('express');
// 2. 创建应用
const app = express();
// 3. 设置静态资源路径
app.use(express.static('node_modules'));
// 4. 设置模版引擎
//ejs需要安装,ejs直接书写业务逻辑,注意注意:不能写注释,写注释直接报错
app.set('view engine','ejs');
// 5. 设置视图路径
app.set('views','./views');
// 6. 设置路由
app.get|post('/',(req,res)=>{
console.log(req);
res.send('hello world!')
//加载视图:将第二个参数的变量data传递给当前的index.ejs
res.render('index',{变量:数组对象})
res.end();
})
// 7. 设置监听端口
app.listen(3000,()=>{
console.log('服务器在3000端口启动')
})
# Cookie的使用
//cookie需要手动安装 'cookie-parser'
//1.引入cookie
const cookie = require('cookie-parser');
//2.应用cookie
app.use(cookie()) //cookie('dssfsdadasda') 可以设置签名密钥(3的第三个参数要设置是否签名)
//使用签名的cookie通过 req.signedCookies 获取
//3.设置cookie
res.cookie('cookie名','要存储的数据',{maxAge:xxxxx})
//第一个参数:cookie名称
//第二个参数:cookie值
//第三个参数:cookie的配置选项
//domain 域名
//path 路径
//expires 过期时间
//maxAge 有效时间
//httpOnly 只能由web服务器访问
//secure 是否与https一起使用
//signed 是否签名
//4.获取cookie
req.cookies.cookie名
//5.删除cookie
res.clearCookie('cookie名')
# Session的使用
特点:
1.session数据保存在服务器端
2.session是以键和值的形式进行存储
3.session依赖于cookie,每个session信息对应的客户端的标识保存在cookie中
//express-session
//1.引入session模块
const session = require('express-session');
//2.注册session
app.use(session({
secret:'sudongxu',//secret属性的值可以为任意字符串,负责进行加密
resave:false, //固定写法,强制保存
saveUninitialized:true //固定写法,保存未初始化
}))
//3.设置session
req.session.自定义属性 = 值
//4.获取session
req.session.自定义属性
//5.清空session
req.session.destroy()
# Socket.io
//环境搭建
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server)
app.use(express.static('node_modules'));
app.set('view engine','ejs');
app.set('views','./views');
app.get('/',(req,res)=>{
res.render('xxx页面')
res.end()
})
server.listen(端口号)
//服务器端
//连接socket服务器
io.on('connection',function(socket){ //形参是一个对象,该对象有两个函数
//服务器端发送给客户端的信息
socket.emit('频道号',{要发送的信息});
//服务器端接收客户端的信息
socket.on('频道号',function(res){
//广播
socket.broadcast.emit('频道号',res)
})
})
//客户端
引入文件
<script src="/socket.io/socket.io.js">
//使用
let socket = io.connect('/')
//客户端发送给服务器端的信息
socket.emit('频道号',{要发送的信息})
//客户端接收服务器端的信息
socket.on('频道号',function(res){})