likes
comments
collection
share

Vue + Koa 全栈小demo,切图小子迈向Full stack engineer的第一步!

作者站长头像
站长
· 阅读数 20

前言

在程序员的圈子里,存在着这么一条鄙视链,做算法的瞧不上做后端开发的,做后端开发的瞧不上做前端的。做为鄙视链底端的前端工程师素来被人们称之为切图崽,但是前端工程师们要自信,我们也是可以做后端滴。接下来,将展示一个适合前端工程师入门全栈的一个全栈小demo。

源码地址:gitee.com/pigs-like-p…

实现效果:

技术栈

前端

vue、pina(状态管理神器)、less(css与编译器)、vant(移动端的ui库)

后端

koa、mysql

前端部分技术难点

请求拦截

在编写项目的过程中,我们经常会碰到以下场景;

当客户端向服务端发送请求时,服务端需要鉴定客户端是否有权限访问服务端的接口。在客户端向服务端发送请求时,通常会给客户端加上一个标识用来标记拥有访问服务端的权利。这个过程是一个授权的过程,通常的解决办法是在请求头上加上一个授权码,那么我们总不能每次在发接口请求的时候都手动添加一个授权码吧。为了解决这个问题,通常会对axios进行请求拦截,这样会将每次请求都拦截下来,可以进行添加授权码的这样一个过程。

请求拦截的代码实现:

//请求拦截
axios.interceptors.request.use(req => {
    let jwtToken = window.localStorage.getItem('token')
    if (jwtToken) {
        req.headers.Authorization = jwtToken
    }
    return req
})

这段代码实现了 Axios 库的请求拦截器功能,在每个 HTTP 请求发出之前都自动添加 JWT(JSON Web Token)到请求头部的 Authorization 字段,以便进行身份验证。

通过这种方式,你不需要在每次发出请求时手动添加 JWT 到请求头,而是可以通过请求拦截器自动化这一过程,简化了代码并提高了安全性。不过,值得注意的是,通常在 Authorization 字段前加上 "Bearer " 前缀是标准做法,例如:

req.headers.Authorization = `Bearer ${jwtToken}`;

这样更符合 HTTP API 的规范。

响应拦截

响应拦截,顾名思义是对服务端响应给客户端的HTTP请求的拦截,用于处理从后端接收到的 HTTP 响应。响应拦截器允许你在响应被传递给 .then() 或 .catch() 处理器之前,对响应进行预处理。

//响应拦截 过滤后端返回来的数据
axios.interceptors.response.use(res => {
    //console.log(res,'111')
    if (res.status !== 200) {//程序错误
        showToast("服务器异常")
        return Promise.reject(res)
    } else {
        if (res.data.state === 401) {//登录失效
            showToast(res.data.msg);
            router.push('/login')
            return Promise.reject(res)

        }
        if (res.data.code !== '8000') {//逻辑性错误
            showToast(res.data.msg)
            return Promise.reject(res)
        }
        //showToast('登录成功')
        return res.data

    }
})
  1. if (res.status !== 200) { ... }

    • 检查响应的状态码是否不是 200(OK)。如果不是 200,通常表示服务器端发生了错误,此时会调用 showToast("服务器异常") 显示一个错误消息,并通过 Promise.reject(res) 抛出一个 Promise 错误,阻止正常的响应处理流程。
  2. if (res.data.state === 401) { ... }

    • 如果响应数据中的 state 属性等于 401,这通常表示未授权或登录状态已失效。此时会显示错误消息 showToast(res.data.msg),将用户重定向到登录页面 router.push('/login'),并同样通过 Promise.reject(res) 抛出错误。
  3. if (res.data.code !== '8000') { ... }

    • 如果响应数据中的 code 不等于 '8000',这可能表示业务逻辑上的错误。此时会显示错误消息 showToast(res.data.msg),并通过 Promise.reject(res) 抛出错误。
  4. return res.data

    • 如果以上条件都不满足,即响应是成功的且没有错误,那么拦截器将直接返回 res.data,即后端返回的实际数据,以便后续的 .then() 处理器可以正常处理这些数据。

通过这样的响应拦截器,你可以统一处理各种类型的错误,比如服务器错误、未授权错误以及业务逻辑错误,而无需在每个请求的 .then() 或 .catch() 处理器中重复相同的错误处理代码。

后端部分技术难点

前端鉴权

在一些业务场景中需要对用户的权限进行鉴定,判断其是否可以访问某些页面。比如下面这样一个场景;

张三是一个网购爱好者,他在访问购物网站时,是不需要登录就可以浏览商品信息,但是当他需要下单某件商品时,他必须要登录账号,这样一个过程就是鉴权的过程。

那么怎么实现这样一个鉴权的过程呢?这个时候JWT就有大作用了。

我们可以在前端访问后端时,为每一个用户都创建一个独特的JWT令牌,在访问后端接口的时候将该令牌携带上,在后端编写代码来识别该令牌的正确性。

如何创建JWT令牌

在后端中我们可以引入,jsonwebtoken库,利用它来生成jwt令牌。

const jwt = require('jsonwebtoken')

通过编写下面的代码可以根据用户传入的数据和自定义的jwt密钥来生成独特的jwt令牌。

前端传给后端的数据:

 const res = await axios.post('/user/login', {
        username: values.username,
        password: values.password
    })

后端中的option参数接受前端传来的数据创建jwt令牌

//创建token
function sign(option) {
    return jwt.sign(option, '666', {
        expiresIn: '86400'//一天后过期
    });
}

当接口请求成功后,可以看到,我们根据用户传入的内容创建了一个独一无二的jwt令牌

Vue + Koa 全栈小demo,切图小子迈向Full stack engineer的第一步!

校验token

在创建了jwt令牌后,之后只要是涉及到鉴权的过程则会调用该函数通过判断jwt是否正确来决定是否可以调用相关的接口。

//检验token
function verify() {
    return async (ctx, next) => {
        let jwtToken = ctx.req.headers.authorization;
        if (jwtToken) {
            //判断token是否合法
            const decoded = jwt.verify(jwtToken, '666',)
            console.log(decoded)
            try {
                const decoded = jwt.verify(jwtToken, '666')
                if (decoded.id) {//合法
                    ctx.userId = decoded.id
                    await next()//调用next 去到下一个中间件
                }
            } catch (e) {
                ctx.body = {
                    status: 401,//权限不足
                    msg: 'token失效'
                }
            }
        } else {
            ctx.body = {
                status: 401,
                msg: '请提供token'
            }
        }
    }
}

verify 中间件的作用是确保每个到达它的请求都携带了一个有效的 JWT,从而实现基于 JWT 的身份验证。如果 JWT 缺失或无效,中间件会立即终止请求处理并返回相应的错误响应。如果 JWT 合法,中间件将继续请求的处理流程,同时将用户 ID 附加到上下文中,供后续的处理逻辑使用。

数据库操作

node的出现赋予了js这门编程语言操作数据库的能力,那么怎么使用js来对数据库进行增删改查的操作呢? 各位请看下面这段代码:

//封装一个函数用来连接数据库
const mysql = require('mysql2/promise')

const config = require('../config/index.js')

//线程池
const pool = mysql.createPool({
    host: config.database.HOST,
    user: config.database.USERNAME,
    password: config.database.PASSWORD,
    database: config.database.DATABASE,
    port: config.database.PORT
})
const allServices = {
    async query(sql, values) {
        try {
            //通过线程池连接mysql
            const conn = await pool.getConnection()
            //对连接执行某些操作
            const [rows, fields] = await conn.query(sql, values)
            //释放连接
            pool.releaseConnection(conn)
            return Promise.resolve(rows)
        } catch (error) {
            return Promise.reject(error)
        }

    }
}

这段代码封装了一个用于连接 MySQL 数据库的函数,利用 mysql2/promise 模块,该模块提供了基于 Promise 的 API,使异步数据库操作更加简洁和易于管理。

  1. 引入模块

    • const mysql = require('mysql2/promise'):导入 mysql2 模块的 Promise 版本,它提供了异步的数据库操作接口。
    • const config = require('../config/index.js'):导入配置文件,其中包含了数据库连接的配置信息,如主机名、用户名、密码、数据库名和端口号。
  2. 创建连接池

    • const pool = mysql.createPool({...}):使用 mysql.createPool 方法创建一个连接池。连接池可以复用数据库连接,避免频繁的建立和断开连接,提高应用程序的性能。这里使用了从配置文件中读取的数据库连接参数。
  3. 定义查询函数

    • allServices.query(sql, values):定义了一个异步方法 query,它接受 SQL 查询语句和参数值作为输入。

    • try { ... } catch (error) { ... }:使用 try-catch 结构来捕获并处理可能发生的错误。

    • const conn = await pool.getConnection():从连接池中获取一个数据库连接。 - const [rows, fields] = await conn.query(sql, values):使用获取到的连接执行 SQL 查询。conn.query 方法返回一个 Promise,该 Promise 解析为一个数组,其中第一个元素是查询结果(rows),第二个元素是字段信息(fields)。

    • pool.releaseConnection(conn):查询完成后,释放数据库连接,将其放回连接池,以便其他请求可以重用。

    • return Promise.resolve(rows):如果一切顺利,将查询结果 rows 包装成一个 Promise 并返回。

通过上述封装,allServices.query 函数提供了一个简单而强大的接口,我们可以调用上述函数,然后传入相应的sql语句就可以进行数据库的增删改查操作了。

Vue + Koa 全栈小demo,切图小子迈向Full stack engineer的第一步!

总结

该全栈demo综合实现了前端与后端的主流业务,个人觉得是一个很好的从前端迈向后端的练手小项目,如需源码的朋友请到文章开头处自行访问。

希望能对大家有所帮助。

Vue + Koa 全栈小demo,切图小子迈向Full stack engineer的第一步!

转载自:https://juejin.cn/post/7393700271128264713
评论
请登录