node.js环境搭建及核心

1.1前置内容

1.1.1什么是javascript

概念:遵循ECMAScript标准,是ECMAscript的具体实现,并且支持浏览器的API,BOM和DOM,并且支持node.js的API.

1.1.2什么是node.js

概念:基于chromev8引擎实现的javascript运行环境。

1.2Node.js下载安装

官网下载

1.3配置npm全局安装目录

进入高级系统设置,环境变量中找到系统变量中找到path中添加文件路径就可以了

1.4配置系统环境变量

2.0Node.js的核心API

2.1文件操作

步骤:
第一步:引入’fs’模块
代码:

// 引入fs模块
var fs = require(fs);

第二步:操作API
示例代码
同步写入

var fs = require(fs);
//同步写入
let rel = fs.writeFileSync('./abc.txt','你好')
console.log(rel);

异步写入

fs.writeFile('孤勇者.txt','爱你孤身走暗巷,爱你不跪的模样',function (err,) {
    if (err) {
        return console.error('输出错误',err);
    }
    console.log('输出完毕');
});

同步读取

let data = fs.readFileSync('./abc.txt')
console.log(data.toString());

异步读取

fs.readFile('./abc.txt',function(err,data){
    console.log(data.toString());
})

删除文件

fs.unlink('./abc.txt',function(){
    console.log('删除成功')
})

创建目录

fs.mkdir("./小钱钱",function(err){
    if (err) {
        return console.error(err);
    }
    console.log("目录创建成功。");
 });

删除目录

fs.rmdir("./小钱钱",function(err){
    if (err) {
        return console.error(err);
    }
    console.log("读取 /tmp 目录");
 });

创建递归目录

fs.mkdir("./得爱者/孤勇者",{recursive : true},function(err){
    if (err) {
        return console.error(err);
    }
    console.log("目录创建成功。");
 });

2.2路径操作

示例代码
引入路径模块

var path = require('path')

返回当前执行脚本的绝对路径

let url = path.resolve('dist')
console.log(url);

拼接一个路径(!加__dirname是绝对路径,不加是相对路径。)

let url = path.join(__dirname,'a,b,c,d.txt')
console.log(url);

2.3node全局对象

1.__filename(当前正在执行的脚本文件名)
2.__dirname(当前正在执行的脚本所在目录)
3.setTimeout(全局函数在指定毫秒数后执行指定函数)
4.clearTimeout(全局函数用于停止一个之前通过 setTimeout() 创建的定时器)
5.setInterval( 全局函数在指定的毫秒(ms)数后执行指定函数(cb))
6.console
7.process(process 是一个全局变量,即 global 对象的属性)

2.4web模块

var http = require('http')
var fs = require('fs')
var url = require('url')
var querystring = require('querystring')

var app = http.createServer(function(req,res){

    //使用 url 模块解析get请求的路由和参数对象
    let path = url.parse(req.url,true)
    console.log(path.pathname); //请求的路由
    console.log(path.query); //请求参数对象
    
    //使用querystring解析post请求
    let postData = ''
    req.on('data', function(data){
        postData += data
    })
    
    req.on('end', function(){
        //解析后的post请求参数对象
        let body = querystring.parse(postData)
    })


	/*
		根据路由判断请求的页面,使用fs响应 html 页面内容
	*/
    // let url = req.url
    // let filePath = '.'
    // console.log(url);

    // if(url === '/' || url === '/index.html'){
    //     filePath += '/index.html'
    // }else if(url === '/job.html'){
    //     filePath += url
    // }else if(url === '/about.html'){
    //     filePath += url
    // }else{

    // }

    // if(url === '/'){
    //     url = '/index.html'
    // }

    // if(url !== '/favicon.ico'){
    //     let data = fs.readFileSync(`.${url}`)
    //     res.write(data.toString())
    // }

    res.end()
})

app.listen(9990)

3.0Express框架

3.1、搭建 Express 开发环境

# 安装express脚手架,此命令不需要每次执行
$ cnpm i express-generator -g

# 创建项目
$ express -e jd-server

# 进入项目根目录
$ cd jd-server

# 初始化依赖
$ cnpm i

package.json 文件中,修改启动命令:

{
    "scripts": {
        "start": "nodemon ./bin/www"
    }
}

3.2、项目目录结构

- public 服务器的静态资源文件管理目录
- routes 路由管理目录
- views 网页模板文件管理目录
- app.js 入口文件
- package.json NPM配置文件

3.3、创建模块的流程

以学生模块为例,创建步骤:

第1步:创建路由文件

routes 目录下创建 stu.js/routes/stu.js 示例代码:

var router = require('express').Router();

//跳转添加学生页面
router.get('/page/add', function(req,res){
    //渲染模板
    res.render('stu_add')
})

module.exports = router

第2步:创建一级路由

app.js 入口文件中注册一级路由,app.js 示例代码:

var express = require('express')
//引入路由文件
var stuRouter = require('./routes/stu.js')

var app = express()

//声明一级路由
app.use('/stu', stuRouter)

第3步:创建模板文件

/views 目录下创建 stu_add.ejs 文件,/views/stu_add.ejs 示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>添加学生</h1>
    <form action="/stu/add" method="POST">
        <div>
            学生姓名:<input type="text" name="stuname">
        </div>
        <div>
            学生年龄:<input type="text" name="age">
        </div>
        <div>
            <button type="submit">提交</button>
        </div>
    </form>
</body>
</html>

第4步:创建添加学生数据的路由

/routes/stu.js 文件中添加 /add 二级路由,/routes/stu.js 示例代码:

var router = require('express').Router();

router.get('/page/add', function(req,res){
    res.render('stu_add')
})

//添加以下代码
router.post('/add', function(req,res){
    //接收post请求参数
    let stu = req.body
    
    //添加数据库
})

module.exports = router

4、Mongodb数据库

4.1、安装 MongodbMongodb Compass

4.2、Node中操作 Mongodb

4.2.1、使用 mongoose

安装

$ cnpm i mongoose --save
$ cnpm i cors --save

4.2.2、连接数据库

例如,在 express 项目中的某个路由文件中实现连接数据库操作,routes/index.js文件,示例代码:

var express = require('express');
var router = express.Router();

//1.引入mongoose
var mongoose = require('mongoose')

//2.连接数据库
mongoose.connect('mongodb://localhost:27017/blog',{
  useNewUrlParser:true
}).then(()=>{
  console.log('数据库连接成功');
}).catch(err=>{
  console.log('数据库连接失败');
})

//3.创建文档模型对象
var schema = new mongoose.Schema({
  title: String,
  createTime: Number,
  author: String,
  content: String
})
var Article = mongoose.model('articles',schema)

//查询文章
router.get('/find', (req,res)=>{

  //find(where) 查询多条数据的方法,参数为查询条件
  Article.find().then(result=>{
     //查询到的结果数组
  })
})

//添加文章
router.post('/add', (req,res)=>{
  //create(obj) 添加方法,参数为要添加的对象
  Article.create().then(result=>{
    	//result 为添加成功的对象
  })
})


module.exports = router;

文档对象的 API(以 Goods 为例):

//添加数据,create(g)参数为要添加的对象,执行成功后返回的是添加成功的对象
Goods.create(g).then(rel=>{}).catch(err=>{})

//修改数据,updateOne()参数1为修改条件,参数2为要修改的新对象,返回修改的结果对象,当 rel.n > 0 时表示修改成功
Goods.updatOne(where,params).then(rel=>{}).catch(err=>{})

//删除数据,findOneAndDelete()参数为删除条件,返回删除成功的对象
Goods.findOneAndDelete(where).then(rel=>{}).catch(err=>{})

//查询所有,find()参数为查询条件
Goods.find(where).then(rel=>{}).catch(err=>{})

//排序查询所有,sort()参数为排序条件 {price: 1}为价格升序,{price: -1}为价格降序,多条件语法 {price:1, sal: -1}
Goods.find().sort({price: -1,createTime: -1}).then(rel=>{}).catch(err=>{})

//分页查询,start表示查询的起始位置(索引),pageSize表示每页查询的条数
//start = (当前页码 - 1) × 每页条数
Goods.find().skip(start).limit(pageSize).then(rel=>{}).catch(err=>{})

//查询总记录数,find()参数为查询条件,返回当前数据的总数量
//总页数 = Math.ceil(count/pageSize)
Goods.find(where).count().then(rel=>{}).catch(err=>{})
Goods.find(where).countDocuments().then(rel=>{}).catch(err=>{})

//模糊查询,查询对象为一个包含正则表达式的条件对象
Goods.find({title: {$regex:  /['裤']|['男']/}}).then(rel=>{}).catch(err=>{})

//比较查询,查询条件中 $gt表示大于,$lt表示小于
Goods.find({price: {$gt: 200, $lt: 300}}).then(rel=>{}).catch(err=>{})

//自增
Goods.updateOne({_id: goods._id}, {$inc: {see: 1}}).then(rel=>{}).catch(err=>{})

此处以添加商品分类为例。

4.2.3、前端请求

使用 jquery 中的异步请求方法:

$.get(url, callback)
$.post(url, params, callback)

使用 vue.js 实现页面 DOM 渲染:

//实例化vue
new Vue({
    //选项
})

Vue的选项:

  • el
  • data
  • methods
  • created
  • filters
  • watch

Vue的指令:

  • v-text
  • v-html
  • v-if/v-else-if/v-else
  • v-show
  • v-for
  • v-bind
  • v-on
  • v-model

扩展:

  • layer 弹框插件
  • layui 前端框架
  • wangEditor 富文本编辑器
  • ECharts 数据可视化

4.3、Node 服务端模块的实现流程

4.3.1、核心业务逻辑封装

连接数据库

在项目根目录下创建 db/index.js 文件,代码:

var mongoose = require('mongoose')

function dbConnect(){
    mongoose.connect('mongodb://localhost:27017/blog',{}).then(()=>{]}).catch(()=>{})
}

module.export = dbConnect

app.js 入口文件引入并调用连接数据库的方法:

var express = require('express')
var dbConnect = require('./db/index.js')

var app = express()
dbConnect()

封装模型对象

以文章模块Article 为例,创建 models/Article.js 文件,代码:

var mongoose = require('mongoose')

//创建配置对象的规则
var schema = new mongoose.Schema({
    title: String,
    see: { //查看次数
        type: Number,
        default: 0
    }
})

//创建模型对象
var Article = mongoose.model('articles', schema)

module.exports = Article

Article.jsmodels/index.js 中向外暴露,代码:

module.exports = {
    Article: require('./Article.js')
}

在其他文件中使用 Article 模块,代码:

// routes/article.js文件

var Model = require('../models')

Model.Article //获取Article模型对象

封装CRUD代码

创建 controller/index.js 文件,代码:

/**
 * 添加数据的方法
 * @param {*} model 模型对象
 * @param {*} params 要添加的参数对象
 * @param {*} res 响应对象
 */
function add(model, params, res){
    model.create(params).then(rel=>{
        if(rel){
            res.json({
                code: 200,
                msg: '添加成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '添加失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '添加时出现异常'
        })
    })
}

/**
 * 修改数据的方法
 * @param {*} model 模型对象
 * @param {*} where 修改条件
 * @param {*} params 修改后的对象
 * @param {*} res 响应对象
 */
function update(model, where, params, res){
    model.updateOne(where, params).then(rel=>{
        if(rel.modifiedCount > 0){
            res.json({
                code: 200,
                msg: '修改成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '修改失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '修改时异常'
        })
    })
}

/**
 * 删除数据的方法
 * @param {*} model 模型对象
 * @param {*} where 删除条件
 * @param {*} res 响应对象
 */
function remove(model, where, res){
    model.findOneAndDelete(where).then(rel=>{
        if(rel){
            res.json({
                code: 200,
                msg: '删除成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '删除失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '删除时异常'
        })
    })
}

/**
 * 分页查询所有数据
 * @param {*} model 模型对象
 * @param {*} page 当前页
 * @param {*} pageSize 每页条数
 * @param {*} where 查询条件
 * @param {*} sort 排序条件
 * @param {*} res 响应对象
 */
async function find(model,page,pageSize,where,sort,res){

    //判断page是否存在
    if(!page){
        page = 1
    }else{
        page = parseInt(page)
        if(isNaN(page)){ //判断是否为数字
            page = 1
        }else{
            if(page < 1){ //判断当前页码不能小于1
                page = 1
            }
        }
    }

    //判断pageSize是否存在
    if(!pageSize){
        pageSize = 10
    }else{
        pageSize = parseInt(pageSize)
        if(isNaN(pageSize)){
            pageSize = 10
        }else{
            if(pageSize < 1){
                pageSize = 3
            }else if(pageSize > 100){
                pageSize = 100
            }
        }
    }

    //总条数
    var count = 0
    await model.find(where).countDocuments().then(rel=>{
        count = rel
    })

    //计算总页数
    var totalPage = Math.ceil(count/pageSize)
    
    //判断page的最大值
    if(totalPage > 0 && page > totalPage){
        page = totalPage
    }

    //计算起始位置
    var start = (page - 1)*pageSize

    await model.find(where).sort(sort).skip(start).limit(pageSize).then(result=>{
        if(result && result.length > 0){
          res.json({
            code: 200,
            msg: '查询成功',
            data: result,
            page,
            pageSize,
            count,
            totalPage
          })
        }else{
          res.json({
            code: 300,
            msg: '没有查询到数据',
            data: []
          })
        }
      }).catch(err=>{
        res.json({
          code: 400,
          msg: '查询时出现异常',
          data: []
        })
      })
}

/**
 * 不分页查询所有数据
 * @param {*} model 模型对象
 * @param {*} where 查询条件
 * @param {*} sort 排序条件
 * @param {*} res 响应对象
 */
function query(model,where,sort,res){
    model.find(where).sort(sort).then(rel=>{
        if(rel && rel.length > 0){
            res.json({
              code: 200,
              msg: '查询成功',
              data: rel,
            })
          }else{
            res.json({
              code: 300,
              msg: '没有查询到数据',
              data: []
            })
          }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '查询时出现异常',
            data: []
        })
    })
}

/**
 * 查询单条数据
 * @param {*} model 模型对象
 * @param {*} where 查询条件
 * @param {*} res 响应对象
 */
function findOne(model, where, res){
    model.findOne(where).then(rel=>{
        if(rel){
            res.json({
              code: 200,
              msg: '查询成功',
              data: rel,
            })
          }else{
            res.json({
              code: 300,
              msg: '没有查询到数据',
              data: {}
            })
          }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '查询时出现异常',
            data: null
        })
    })
}

module.exports = {
    add,
    update,
    remove,
    find,
    findOne,
    query
}

4.3.2、JWT 使用

安装 jsonwebtoken

$ cnpm i jsonwebtoken --save

生成token

一般会在登录的路由中生成 token,例如 routes/user.js 文件中:

var router = require('express').Router()
var jwt = require('jsonwebtoken')

//管理员登录
router.post('/login',async function(req,res){
    let u = req.body //接收参数
    
    //数据库查询,查询成功后,生成token 
    let user = {}
    
    // expiresIn 有效期,单位秒
    let token = jwt.sign(user,'密钥',{expiresIn: 60 * 60 * 24 * 7})
    
    res.json({
        code: 200,
        token
    })
})

module.exports = router

前端接收token

login.html

<script>
	$.post('url', {}, function(res){
        if(res.code === 200){
         localStorage.token = res.token    
        }
    })
</script>

验证token

前端发送请求,将 token 放到请求头

<script>
	$.ajax({
        url: '',
        headers: {
            token: localStorage.token
        }
    })
</script>

在服务端验证 token ,一般会放到 app.js 的中间件内:

app.js 代码:

var express = require('express')
var jwt = require('jsonwebtoken')

var app = express()

//验证token(中间件)
//配置不进行校验的路由
let pathRule = [
  '/admin/user/login',
  '/user/reg',
  '/user/login',
]
app.use(function(req,res,next){
  if(pathRule.includes(req.path)){
    next()
    return
  }

  //获取token
  var token = req.headers.token
  let result = null

  //验证token
  jwt.verify(token,'密钥',function(err,data){
      if(err){
          switch(err.name){
              case 'JsonWebTokenError':
                  result = {
                      errCode: 1,
                      msg: '无效token'
                  }
                  break;
              case 'TokenExpiredError':
                  result = {
                      errCode: 2,
                      msg: 'token过期'
                  }
                  break;
          }
      }else{
          result = {
              errCode: 0,
              data: {
                  username: data.username,
                  role: data.role
              }
          }
      }
  })

  if(result.errCode == 0){
    next()
  }else{
    res.json(result)
  }
})

//路由
app.use('/user', xxx)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值