what‘s node?
node既不是一种语言,也不是一个框架,更不是一个库。而是一种能让JavaScript运行在服务器上的一个平台
首先要下载node.js 自行到官网中下载。注意两个版本的区别
node中是以模块来划分作用域
node里面分为两个作用域,全局作用域(glogbal)和模块作用域
例如我们想要读取一个txt文件,JavaScript中是不可能实现的
let fs = require ('fs' )fs.readFile('txt路径' ,(erro,data)=>{ console .log(erro) console .log(data) console .log(data.toString()) });
基本上路径如果,对的话是没有问题的,还有可能文件不存在。
现在我们不止想要读一个文件,我还想写入一个文件 let fs = require ('fs' )fs.writeFile('路径' ,'文件内容' ,error=>{ if (error){ console .log('文件写入失败' ) }else { console .log('文件写入成功' ) } })
http模块 let http = require ('http' )let server = http.createServer((req,res )=> { url = req.url if (url === '/' ){ res.end('http 的使用' ) } }) server.listen(3000 ,()=>{ console .log('running is server...' ) })
exports和module exports的区别
很多时候我们需要引入到别的模块中的变量,这个时候我们就需要使用的exports或者module.exports来暴露我们需要使用的变量或者对象。每一个模块中都有一个module.exports对象,每一个module.exports对象都有一个exports对象,所以我们把需要暴露的对象都挂载在module.exports对象上。所以每次暴露都是module.exports.xxx = xxx但是为了方便同时又在每一个模块中提供了一个exports成员,还有exports === module.exports是为true假如我们只需要暴露xxx我们可以直接exports.xxx即可
如果我们暴露单个成员则需要使用module.exports不能使用exports因为最终返回的都是module.exports即使exports=xxx也不行,
但是有一种特别的特殊方法 exports=module.exports是可以的,
多次暴露使用exports
单次暴露使用module.exports
module.exports也可以多个暴露(module.exports={}即可)
Express 一、安装express框架(npm i -S express)
引入express模块
定义变量接受express()方法
利用express实现helloworld
let express = require ('express' )let app = express()app.get('/' ,(req,res)=>{ res.send('hello world' ) }) app.get('/login' ,(req,res)=>{ res.send('login' ) }) app.listen(3000 ,()=>{ console .log('server is running' ) })
总的来说比我们之前写原生简单易懂的多。
二、nodemon的使用 每一次修改完代码是不是每一次都要node app.js 还要每一次都要开启服务器。nodemon是我们每一次修改完代码后只要ctrl+s然后刷新浏览器就可以更改。
npm i -g nodemon(安装nodemon)
nodenom -v (查看版本号)
nodemon xxx.js(运行js文件)
三、模板引擎的使用
先下载art-template
使用engine(’以什么文件后缀’,’express-art-template’)引入express-art-template包
使用路由get()方式
使用render(‘渲染的文件’,{对象数据}) 默认到views文件夹中去寻找,若要修改则app.set(‘views’,’文件夹路径’)
let express = require ('express' )let app = express()app.engine('html' ,require ('art-template-express' )) app.get('index.html' ,(req,res)=>{ res.render('index.html' ) }) let bodyParser = require ('body-parser' )app.use(bodyParser.urlencoded({ extended : false })) app.use(bodyParser.json()) app.get('/pinglun' ,(req,res)=>{ let comment = req.query comment.dataTime = '2019-5-1' comments.unshift(comment) res.redirect('/' ) }) app.post('/post' ,(req,res)=>{ let comment = req.body comment.dataTime = '2018-3-5' comments.unshift(comment) res.redirect('/' ) })
四、提取路由模块 我们每一次写路由的时候都会用很多的页面,那么这个时候都写在app中似乎有些不妥,这个时候我们可以把路由模块单独提取出来,生成一个router.js 而app.js只作为入口文件,具体操作如下。
app.js
let express = require ('express' )let app = express()let router = require ('./router' )app.use(router) app.listen(3000 ,()=>{ console .log('server is running' ) })
router.js
let express = require ('express' )let router = express.Router()router.get('/' ,(req,res)=>{ res.send('index' ) }) router.get('/login' ,(req,res)=>{ res.send('login' ) }) router.get('/register' ,(req,res)=>{ res.send('register' ) }) module .exports = router
把路由与入口文件这个样子就可以彻底分开,这样感觉显得更加整洁。
五、静态资源库的开放 在这里我们首先来看path模块中的join函数和dirname与 basename
let path = require ('path' )app.use('/public' ,express.static(path.join(__dirname,'/public' )))
六、MongoDB 1、准备工作 (1)安装 在官网中下载安装包
分为,完整安装和自定义安装(只要改个路径就行了)一般我们选择完整安装
(2)配置环境变量 完整安装一般默认是放在C盘目录下
(3)测试是否安装成功 一般如果我们在bin目录下直接点击mongod.exe会出现闪退,这也是我们为什么要配置环境变量的原因。
如果出现以上的信息那么就代表我们安装成功。
(4)开启数据库 # mongod 默认使用时会把mongod根目录盘中的/data/db作为数据存储目录 在命令行中输入 mongod
attention: 在第一次开启数据库的时候我们必须要在盘符根目录下(我的是c盘)新建一个/data/db两个文件夹下 ,不然就会出现连接不成功(shutting down)
修改默认路径:mongod –dbpath=数据存储目录
如果新建了文件夹,则会success(看不懂吧。。是的)
(5)关闭数据库 ctrl加c或者点击上面的叉即可 2、连接数据库 (1)默认连接本地数据库
(2)在连接的时候退出数据库
(3)基本命令
show dbs
use “数据库名称”
db
show collections
show.[collections].find()
这里需要说明一下,如果直接db的话,会出现test,但是我们show dbs的时候却没有test这个数据库,这是怎么回事呢?这个原因是因为我的test的数据库中没有数据,如果插入数据的话,再show dbs的话,则会出现test数据库(任何一个空的数据库都是这样,除非里面有数据,否则的话不会出现)
举个例子吧(假设下面的是终端)
//创建或者切换数据库 use itcast //向当前数据库中插入一个集合并且插入数据 db.students.insertOne({"name":"jack"}) //查看数据库(插入成功的话就会有这个数据库,相反却没有) show dbs //查看当前数据库的集合(应该会是students) show collections //查看当前集合中的所有元素({ "_id" : ObjectId("5ca346b9b0e4018e76041ca1"), "name" : "jack" }) db.students.find()
3、MongoDB基本概念 看到黑马视频一个描述MongoDB的挺有意思的:
最外层的括号相当于MongoDB
qq,taobao,baidu。。相当于我们里面有很多数据库
user,product。。相当于数据库中的集合
name,age集合中的记录
{ qq:{ user:[ {"name" :"张三" ,age :15 }, {"name" :"张三34" ,age :25 }, {"name" :"李四" ,age :35 }, {"name" :"张三34" ,age :45 }, .... ], product:[ .... ], }, taobao:{ ... }, baidu:{ } }
4、使用mongoose操作mongodb (1)安装mongoose包(npm i mongoose)
(2)引入mongoose模块 (let mongoose = require(mongoose))
(3)创建架构
(4)连接数据库
(5)设计结合的结构
(6)将文档结构发布为模型
let mongoose = require ('mongoose' )let Schema = mongoose.Schemamongoose.connect('mongoose://localhost/数据库名称' ) let userSchema = new Schema({ username: { type: String , required: true , }, password: { type: String , required: true }, email: { type: String } }) let User = mongoose.model('User' ,userSchema)
5、增加数据 let admin = new User({ username: 'zs' , password: '123456' , email: '3199895@qq.com' }) admin.save((err,ret )=> { if (err){ console .log('保存失败' ) }else { console .log('保存成功' ) console .log(ret) } })
6、查询数据 User.find((err,ret )=> { if (err){ console .log('查询失败' ) }else { console .log(ret) } }) User.findOne({ username: 'zs' },(err,ret)=>{ if (err){ console .log('查询失败' ) }else { console .log(ret) } })
7、删除数据 User.remove({ username: 'zs' },(err,ret)=>{ if (err){ console .log('删除失败' ) }else { console .log(ret) console .log('删除成功' ) } })
8、更新数据 User.findByIdAndUpdate('5ca35aaa914afc2efceed812' ,{ password: '123456' },function (err,ret ) { if (err){ console .log('更新失败' ) }else { console .log(ret) console .log('更新成功' ) } })
第二篇 对象
全局对象:随时都能访问
process.env
__filename(获取当前运行文件的绝对路径)
__dirname(获取当前运行文件目录的绝对路径)
内置对象:向系统索要,引入即可
自定义对象:引入正确的路径即可
node所实现的规范
CommonJS:规范nodeJS作为后端运行的标准
模块应该怎么写module
依赖某一模块require
被依赖的模块需要module.exports = 外部数据
一个文件就是一个模块
文件的读取和写入
如果要对文件进行操作,就要先引入文件模块fs
readFile (文件路径和名,’utf-8’,回调函数)异步读取文件的内容
readFileSync()同步读取文件的内容
writeFile(文件的路径和名,文件内容,回调函数)
const fs = require ("fs" );fs.readFile("./public/a.txt" ,"utf-8" ,(err,data)=>{ if (err) throw err; console .log(data); }) fs.writeFile("./public/b.txt" ,"哈哈哈,几天也是很难熬的一天啊" ,(err)=>{ if (err) throw err; console .log("写入文件完成" ); })
http
http是node中的核心模块,同样的要先引入
createServer()创建一个本地的服务器
http.on()执行request请求,并有一回调函数,获取到request和,response参数。
request是只读不能写入
response是可以写入
http.listen(端口号,回调函数)用以开启服务器
const http = require ('http' )const port = process.env.PORT | 3000 http.createServer((req,res )=> { res.setHeader('a' ,'a' ) res.setHeader('c' ,'c' ) res.writeHead(200 ,{'content-type' :'text/html;charset=utf-8' }) res.write('第一次写入' ) res.end('最后一次写入' ) }) .listen(port,()=>{ console .log(`server is running ${port} ` ) })
状态码
1开头正在执行
2开头已完成
3开头重定向
4开头客户端出现错误
5开头服务端出现错误
连接Mysql数据库
npm i mysql -g(全局下载项目依赖模块)
复制对应代码
var mysql = require('mysql'); var pool = mysql.createConnection({ host: 'localhost', user: 'root', password: '', database: 'node_music' }); pool.connect() let db = {} db.q = function(sql,params){ pool.query(sql, params,function (error, results, fields) { if (error) throw error; else{ console.log('成功插入到数据库中') console.log(results) pool.end() } }) } module.exports = db
KOA框架
主要介绍koa框架,express在上一篇文章已经介绍过了。koa框架是express的作者是同一个人,比起express(太大,太全)反而koa(轻量级,按需引入)
引入koa
创建一个koa对象
处理响应
开启服务器
koa是非常智能的,如果我们读一个二进制的文件,它会帮我们下载下来。
另外需要注意的是:koa采用的是es7中的async 和await需要和promise联合使用,废弃掉了express采用回调函数的机制
中间件的使用也是按需引入,比较方便
koa-bodyparser const Koa = require ('koa' )const bodyParser = require ('koa-bodyparser' )const app = new Koa()app.use(bodyParser()) app.use( async ctx => { ctx.body = ctx.request.body }) const port = process.env.PORT || 3000 app.listen(port,()=>{ console .log(`server is running ${port} ` ) })
const db = require ('./db_test_01' )db.q(`insert into users (title,single,time,file,uid) values(?,?,?,?,?)` ,['小菜' ,'青花瓷' ,'03:00' ,'d:/' ,6 ])
koa-router**
npm i koa-router
引入路由模块
创建对象
和app相关联
const Koa = require ('koa' )const bodyParser = require ('koa-bodyparser' )const Router = require ('koa-router' )const app = new Koa()const router = new Router()router.get('/' ,async ctx => { ctx.body = '首页' }) .post('/post' ,async ctx => { ctx.body = ctx.request.body }) app.use(router.routes()) app.use(bodyParser()) app.use(router.allowedMethods()) const port = process.env.PORT || 3000 app.listen(port,()=>{ console .log(`server is running ${port} ` ) })
路由嵌套
koa中把路由模块单独抽离出来,是希望可以开发大型的企业项目,可以有多级的路由嵌套。
以下是我们的目录树:
├─03_koa_router │ │ app.js │ └─router ├─cat ├─new └─user admin.js company.js index.js
app.js中我们需要引入
router.use('/user' ,require ('./router/user' )) app.use(router.routes())
index.js
koa-art-template**
const Koa = require ('koa' )const path = require ('path' )const Router = require ('koa-router' )const render = require ('koa-art-template' )const app = new Koa()const router = new Router()render(app,{ root: path.join(__dirname,'view' ), extname: '.html' , debug: process.env.NODE_ENV !== 'production' }) router.get('/' ,async ctx => { ctx.render('index' ) }) app.use(router.routes()) app.use(router.allowedMethods()) const port = process.env.PORT || 3000 app.listen(port,()=>{ console .log(`server is running ${port} ` ) })
koa-static
这里面有点难以理解,我们只需要在上面的代码加上以下的两句代码即可,但是我们的index.html中的
//这里面不需要写目录文件夹名,一旦写就错了,如果写的话,我们需要判断
const static = require(‘koa-static’)
app.use(static(path.resolve(‘./js’)))
前端静态写了目录文件夹名称的需要进行判断
app.use(async (ctx,next) => { if (ctx.url.startsWith('/js' )){ ctx.url = ctx.url.replace('/js' ,'' ) } await next() })
koa-session
必须引入koa-session
必须在路由挂载之前
一般都为默认值,不修改
signed如果设置false
则别人会获取到,然后进行解密。再篡改就麻烦了,所以我们一般设置为true,这样就会有个签名和初始值是对应的,修改的话后台会报异常
httpOnly如果为true,我们客户端document.cookie就会获得到。反正不会
const Koa = require ('koa' )const path = require ('path' )const bodyParser = require ('koa-bodyparser' )const Router = require ('koa-router' )const render = require ('koa-art-template' )const static = require ('koa-static' )const session = require ('koa-session' )const app = new Koa()const router = new Router()render(app,{ root: path.join(__dirname,'view' ), extname: '.html' , debug: process.env.NODE_ENV !== 'production' }) router.get('/' ,async ctx =>{ ctx.render('index' ) }) .post('/login' ,async ctx => { let username = ctx.request.body.username; let password = ctx.request.body.password; if (username != "admin" || password != "123" ){ ctx.throw(200 ,'有急事去啦~' ) }else { ctx.session.user = { username: 'admin' } ctx.body = '登录成功' } }) /加密算法字符串/ app.keys = ['some secret hurr' ] const CONFIG = { key: 'koa:sess' , maxAge: 86400000 , overwrite: true , httpOnly: true , 不允许客户端修改cookie signed: true , 数字签名,保证数据不被串改 rolling: false ,过期时间顺延 renew: false , 是否开启一个新的 } app.use(static (path.resolve('./js' )) ) app.use(bodyParser()) app.use(session(CONFIG, app)); app.use(router.routes()) app.use(router.allowedMethods()) const port = process.env.PORT || 3000 app.listen(port,()=>{ console .log(`server is running ${port} ` ) })
以上的方法并不能保证信息的安全性,并且cookie的值还会有长度限制,所以改用以下的方式,解不了密
app.keys = ['some secret hurr' ] let store = { storage: {}, get(key){ return this .storage[key] }, set(key,sess){ this .storage[key] = sess }, destroy (key) { delete this .storage[key] } } app.use(session({store}, app));
koa中出错处理 ctx.throw() app.use(async (ctx,next) => { try { await next() }catch (e){ ctx.status = 200 ctx.body = `<div>你访问的页面失联了</div>` } })
生成key const fs = require ('fs' )const key_len = 1024 const key_count = 2048 let char = 'idOFIGLSFGJKSFGfHSGFHusakjfds#¥#@6556aHGSFff{}D}{:SFJAfdsafJ*(……%5KFSdgfdasfkdsjDJF355435&*' let arr = []for (let i = 0 ; i < key_count; i++){ let key = '' for (let j = 0 ; j < key_len; j++){ key += char[Math .floor(Math .random()*char.length)] } arr.push(key) } fs.writeFileSync('.keys' ,arr.join('/n' )) console .log(`get ${key_count} ` )