前端进阶全栈入门级教程nodeJs博客开发(一)搭建环境与路由

Posted MmM豆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端进阶全栈入门级教程nodeJs博客开发(一)搭建环境与路由相关的知识,希望对你有一定的参考价值。

阅读本篇文章时候,需要前端有一定基础后,想要进阶全栈,或者了解后端工作方式阅读,能更好的提高,前后分离对接的理解,本篇只会,概况的带领操作一遍,后端开发。简单易懂。

一、搭建开发环境

tips 以下注释 // 省略。。。。 均为省略未修改部分

我们先创建文件夹nativBlog

然后使用 npm init -y 初始化一个项目
在这里插入图片描述

  1. 安装nodemon 自动重启node

    npm i nodemon -D
    
  2. 安装cross-env 控制开发环境

    npm i cross-env -D
    

按照下列创建并修改文件,搭建一个基础的nodeSever,并返回一定数据

文件结构

├─app.js
├─package.json
├─src
├─bin
|  └www.js

www.js

const http = require('http')

const PORT = 8000
const serverHandle = require('../app')

const server = http.createServer(serverHandle)
server.listen(PORT)
console.log('已开启 8000端口');

app.js

const serverHandle = (req,res)=>{
  // 设置返回格式 JSON
  res.setHeader('Content-type','application/json')
   //模拟一下假数据 
  const resData = {
    name:'admin',
    env:process.env.NODE_ENV
  }

  res.end(
    JSON.stringify(resData)
  )
}

module.exports = serverHandle

添加启动命令

package.json

{
  "name": "native-blog",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1",
    "dev": "cross-env NODE_ENV=dev nodemon ./bin/www.js",
    "prd": "cross-env NODE_ENV=production nodemon ./bin/www.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "cross-env": "^7.0.3",
    "nodemon": "^2.0.7"
  }
}

运行一下

然后打开浏览器或者postman测试一下

npm run dev

在这里插入图片描述

二、搭建路由

路由和API的概念

API:

前端和后端、不同端(子系统)之间对接的一个术语

前端只需要知道 url(路由)是什么,传递方式和参数,不需要知道如何实现

路由:

API的一部分,

后端系统内部的一个定义,

,比如要实现一个api,需要定义一个router,controller db model等等

(一) 搭建基础路由

以下为我们需要建立的接口

在这里插入图片描述

我们区分blog和user2个部分建立文件

├─src
|  ├─router //处理路由
|  |   ├─blog.js
|  |   └user.js

blog.js

const  handleBlogRouter = (req,res) =>{
console.log('method:',req.method);
console.log(' req.path:', req.path);

  // 获取博客列表
  if(req.method ==='GET'&&  req.path ==='/api/blog/list') {
    console.log('进入2');
    
    return {
      msg:'这是获取博客列表的接口'
    }
  }
  // 获取博客详情
  if(req.method === 'GET'&&  req.path ==='/api/blog/detail') {
    return {
      msg:'这是获取博客详情的接口'
    }
  }
  // 新建一篇博客
  if(req.method === 'POST'&&  req.path ==='/api/blog/new') {
    return {
      msg:'这是新建博客列表的接口'
    }
  }
  // 更新博客列表
  if(req.method === 'POST'&&  req.path ==='/api/blog/update') {
    return {
      msg:'这是更新博客列表的接口'
    }
  }
  // 删除博客列表
  if(req.method === 'GET'&&  req.path ==='/api/blog/del') {
    return {
      msg:'这是删除博客列表的接口'
    }
  }
}
module.exports = handleBlogRouter

user.js

const handleUserRouter = (req,res)=>{
 
  // 登录
  if(req.method === 'POST' &&  req.path === '/api/user/login'){
    return {
      msg:'这是登录的接口'
    }
  }
}
module.exports = handleUserRouter

修改一下原本的app.js 来处理请求

const querystring = require('querystring') //引入原生模块解析get参数
const handleBlogRouter = require('./src/router/blog')
const handleUserRouter = require('./src/router/user')
const serverHandle = (req,res)=>{

    // 设置返回格式 JSON
    res.setHeader('Content-type','application/json')
  // 获取路径
    const url = req.url
    req.path = url.split('?')[0]
  // 解析query
    req.query = querystring.parse(url.split('?')[0])
    // 处理blog路由
    const blogData= handleBlogRouter(req,res)

    if(blogData){
      res.end(
        JSON.stringify(blogData)
      )
      return
    }

    // 处理user路由
    const userData= handleUserRouter(req,res)

    if(userData){
      res.end( 
        JSON.stringify(userData)
      )
      return
}
// 未命中路由返回404
res.writeHead(404,{"COntent-type":"text/plian"})
res.write("404 Not Found\\n")
res.end()
}

module.exports = serverHandle

通过上步,我们简单搭建了一套路由,然后用在psotman来测试一下

在这里插入图片描述

OK,没有问题,当然你需要每个接口都尝试一下

(二)创建controller 和model层

文件结构

├─src
|  ├─router //处理路由
|  |   ├─blog.js
|  |   └user.js
|  ├─model //建立数据模型
|  |   └resModel.js
|  ├─controller //处理业务逻辑
|  |     ├─blog.js
|  |     └user.js


分清楚一个事实,就要分清层级,router只管路由的处理,www.js只管创建sever,controller只管业务逻辑的处理

model 处理返回的数据结构

到这一步,还没连接数据库,但我们要假装模拟一下真实的数据返回

首先建立model

resModel.js

class BaseModel {
  constructor(data, message) {
      // 兼容判断是否传人2个参数
      if (typeof data === 'string') {
          this.message = data
          data = null
          message = null
      }
      if (data) {
          this.data = data
      }
      if (message) {
          this.message = message
      }
  }
}
 //成功的数据模型
class SuccessModel extends BaseModel {
  constructor(data, message) {
      super(data, message)
      this.errno = 0
  }
}

// 失败的数据模型
class ErrorModel extends BaseModel {
  constructor(data, message) {
      super(data, message)
      this.errno = -1
  }
}

module.exports = {
  SuccessModel,
  ErrorModel
}

其次建立controller层

先做个简单的假数据模拟、

blog.js

const getList = (author,keyword) =>{
	//模拟返回的数据,用promise模拟异步数据库操作
  const promise = new Promise((resolve,reject)=>{
    const data = [
      {
        id:1,
        title:"标题A",
        content:"内容A",
        createTime:1600410168761,
        author:"张三"
      },
      {
        id:2,
        title:"标题B",
        content:"内容B",
        createTime:1600410221493,
        author:"李四"
      }
    ]
    resolve(data)
  })
  return promise
}
module.exports = {
  getList
}

然后修改router下bolg.js的处理,修改一个接口来体验一下

blog.js

//导入controller
const {getList} = require('../controller/blog')
//导入model
const {SuccessModel,ErrorModel} = require('../model/resModel')
......省略未修改部分

// 获取博客列表
  if(req.method ==='GET'&&  req.path ==='/api/blog/list') {
    const author = "张三"
    const keyword = "标题A"
    
      const result = getList(author,keyword)
    return result.then(data =>{
        return new SuccessModel(data,'请求成功')
    })
  }
......省略未修改部分

app.js

...省略未修改部分

const serverHandle = (req,res)=>{
...省略未修改部分
            // 处理blog路由
        const blogResult= handleBlogRouter(req,res)
        if(blogResult){
          blogResult.then(blogData =>{
            if(blogData){
              res.end(
                JSON.stringify(blogData)
              )
            }
          })
          return
        }
        // // 处理user路由
        const userResult= handleUserRouter(req,res)
        if(userResult){
          userResult.then(userData=>{
            if(userData){
              res.end(
                JSON.stringify(userData)
              )
              return
            }
          })
        }
...省略未修改部分
}
module.exports = serverHandle

修改完成后用postman来测试
在这里插入图片描述

测试成功,代表我们的模块规划没有问题

(三)处理post请求

前面都是用的get,对于post我们还没做任何处理,post是异步操作,所以我们需要用promise来处理一下

封装一个下面方法来处理post

// 处理post请求
const getPostData = (req) => {
  const promise = new Promise((resolve, reject) => {
    // 不是post,get请求
      if (req.method !== 'POST') {
          resolve({})
          return
      }
      // post请求处理, 如果返回的格式不是json 返回一个空
      if (req.headers['content-type'] !== 'application/json') {
          resolve({})
          return
      }
      let postData = ''
      //   post数据其实是数据流,所以我们需要监听拼接数据
      req.on('data', chunk => {
          postData += chunk.toString()
      })
      req.on('end', () => {
        // 没有数据返回一个空
          if (!postData) {
              resolve({})
              return
          }
          resolve(
              JSON.parse(postData)
          )
      })
  })
  return promise
}

然后app.js完整代码 如下,在处理路由前,先通过封装的方法处理一下post请求

const querystring = require('querystring')
const handleBlogRouter = require('./src/router/blog')
const handleUserRouter = require('./src/router/user')

// 处理post请求
const getPostData = (req) => {
  const promise = new Promise((resolve, reject) => {
    // 不是post,get请求
      if (req.method !== 'POST') {
          resolve({})
          return
      }
      // post请求处理, 如果返回的格式不是json 返回一个空
      if (req.headers['content-type'] !== 'application/json') {
          resolve({})
          return
      }
      let postData = ''
      req.on('data', chunk => {
          postData += chunk.toString()
      })
      req.on('end', () => {
        // 没有数据返回一个空
          if (!postData) {
              resolve({})
              return
          }
          resolve(
              JSON.parse(postData)
          )
      })
  })
  return promise
}

const serverHandle = (req,res)=>{

    // 设置返回格式 JSON
    res.setHeader('Content-type','application/json')
  // 获取路径
    const url = req.url
    req.path = url.split('?')[0]
    // 解析query
    req.query = querystring.parse(url.split('?')[1])
    // 处理post请求
    getPostData(req).then(postData=>{
          req.body = postData
            // 处理blog路由
        const blogResult= handleBlogRouter(req,res)
        if(blogResult){
          blogResult.then(blogData =>{
            if(blogData){
              res.end(
                JSON.stringify(blogData)
              )
            }
          })
          return
        }

        // // 处理user路由
        const userResult= handleUserRouter(req,res)
        if(userResult){
          userResult.then(userData=>{
            if(userData){
              res.end(
                JSON.stringify(userData)
              )
            }
          })
              return
        }
    
    // 未命中路由返回404
    res.writeHead(404,{"COntent-type":"text/plian"})
    res.write("404 Not Found\\n")
    res.end()
  })

   
}

module.exports = serverHandle

之后修改一个post接口来测试一下

controller

blog.js

...省略
const newBlog = (blogData = {}) =>{
  // blogData 包含 title content
  // 添加成功返回添加id,
    //模拟处理完成后返回数据
  const promise = new Promise((resolve,reject)=>{
    const data = {
      id:3
    }
    resolve(data)
  })
  return promise
}
module.exports = {
    ...省略
  newBlog
}

router

blog.js

const {
  ...省略
  newBlog} = require('../controller/blog')
 ...省略

  // 新建一篇博客
  if(req.method === 'POST'&&  req.path ==='/api/blog/new') {
          const result = newBlog(req.body)
      return result.then(data =>{
        return new SuccessModel(data,'添加成功')
    })
  }
 ...省略

通过postman测试一下,

在这里插入图片描述

接下来完善并模拟所有的数据

controller

blog.js

const getList = (author,keyword) =>{
  const promise = new Promise((resolve,reject)=>{
    const data = [
      {
        id:1,
        title:"标题A"以上是关于前端进阶全栈入门级教程nodeJs博客开发(一)搭建环境与路由的主要内容,如果未能解决你的问题,请参考以下文章

前端进阶全栈入门级教程nodeJs博客开发(一)搭建环境与路由

前端进阶全栈入门级教程nodeJs博客开发(一)搭建环境与路由

前端进阶全栈入门级教程nodeJs博客开发(二)安装mysql完善api接口对接mysql

前端进阶全栈入门级教程nodeJs博客开发(二)安装mysql完善api接口对接mysql

前端进阶全栈入门级教程nodeJs博客开发(二)安装mysql完善api接口对接mysql

前端进阶全栈入门级教程nodeJs博客开发(二)安装mysql完善api接口对接mysql