全栈前端入门必看 koa2+mysql+vue+vant 构建简单版移动端博客

2018-08-10 admin

koa2+mysql+vue+vant 构建简单版移动端博客

具体内容展示

开始正文

github地址 <br/>

觉得对你有帮助的话,可以star一下^_^ 必须安装:<br/> mysql <br/> node.js vue-cli<br/>

目录结构

<br/><br/>

代码步骤

<br/> 在 app 目录下 打开 node 运行vue-cli vue init webpack 新建Vue项目<br/> 安装以下依赖模块: <br/>

"axios": "^0.18.0",
"js-cookie": "^2.2.0",
"js-md5": "^0.7.3",
"nprogress": "^0.2.0",
"vant": "^1.1.15",
"vue": "^2.5.2",
"vue-router": "^3.0.1"

详细具体看github源码

koa2 目录下 打开 node 运行 npm init 编写信息<br/> 安装以下依赖模块: <br/>

"jsonwebtoken": "^8.3.0",  // 生成token
"koa-bodyparser": "^4.2.1", // 解析requeset body
"koa-cors": "^0.0.16", // koa跨域
"koa-router": "^7.4.0", // koa-router
"koa-static": "^5.0.0", // koa静态文件
"koa2": "^2.0.0-alpha.7", // koa2
"mysql": "^2.16.0", // mysql
"uuid": "^3.3.2" // 生成userId

<br/>

在 koa2/config.js 进行 mysql 链接配置

// config.js  数据库配置

    module.exports = {  // mysql 配置
      mysql: {
        host: 'localhost', // 地址
        user: 'root', // 用户账号
        password: '', // 密码
        database: 'test' // test库
      },
      port: 3001 // 监听端口
    }

编写 sql 配置

在 koa2/mysql.js 进行编写 sql 语句

// mysql.js   编写sql语句

    const mysql = require('mysql');
    const config = require('./config.js');

    var pool = mysql.createPool(config.mysql);

    const query = function (sql, val) {
      return new Promise((resolve, reject) => {
        pool.getConnection(function (err, connection) {
          if (err) {
            reject(err)
          } else {
            connection.query(sql, val, (err, res) => {
              if (err) {
                reject(err)
              } else {
                resolve(res)
              }
              connection.release();
            })
          }
        })
      })
    }

    const createTable = (sql) => {
      query(sql, [])
    }

    const usersTable = `CREATE TABLE IF NOT EXISTS users (
       id VARCHAR(36) NOT NULL,
       userName VARCHAR(16) NOT NULL,
       passWord VARCHAR(16) NOT NULL,
       avator VARCHAR(50) NOT NULL,
       createTime VARCHAR(50) NOT NULL,
       PRIMARY KEY (id) 
    )`;

    const postsTable = `CREATE TABLE IF NOT EXISTS posts (
       id INT NOT NULL AUTO_INCREMENT,
       userName VARCHAR(100) NOT NULL,
       userId VARCHAR(40) NOT NULL,
       avator VARCHAR(100) NOT NULL,
       title VARCHAR(100) NOT NULL,
       content TEXT(0) NOT NULL,
       hot VARCHAR(40) NOT NULL,
       comments VARCHAR(40) NOT NULL,
       createTime VARCHAR(100) NOT NULL,
       PRIMARY KEY (id) 
    )`;

    const commentTable = `CREATE TABLE IF NOT EXISTS comment (
       id INT NOT NULL AUTO_INCREMENT,
       userName VARCHAR(100) NOT NULL,
       content TEXT(0) NOT NULL,
       postId VARCHAR(40) NOT NULL,
       avator VARCHAR(100) NOT NULL,
       createTime VARCHAR(100) NOT NULL,
       PRIMARY KEY (id) 
    )`;

    // 建表
    createTable(usersTable) // 用户表
    createTable(postsTable) // 文章表
    createTable(commentTable) // 评论表

    const insetUser = (val) => { // 注册
      let _sql = `INSERT INTO users (id, userName, passWord, avator, createTime) VALUES (?,?,?,?,?)`
      return query(_sql, val)
    }

    const findUser = (val) => { // 查找所有User
      let _sql = `SELECT * FROM users WHERE userName = '${val}'`
      return query(_sql)
    }

    const createPosts = (val) => { // 新建posts
      let _sql = `INSERT INTO posts (userName, userId, avator, title, content, hot, comments, createTime) VALUES (?,?,?,?,?,?,?,?)`
      return query(_sql, val)
    }

    const updatePosts = (val) => { // 修改posts
      let _sql = `UPDATE posts SET title=?, content=? WHERE id=?`
      return query(_sql, val)
    }

    const updatePostsComment = (val) => { // 修改posts评论数量
      let _sql = `UPDATE posts SET comments=? WHERE id=?`
      return query(_sql, val)
    }

    const updatePostsHot = (val) => { // 修改posts查看人数
      let _sql = `UPDATE posts SET hot=? WHERE id=?`
      return query(_sql, val)
    }

    const postsList = (key, pg, size) => { // 查找所有posts
      let _sql = `SELECT * FROM posts ${ key ? "WHERE title LIKE '%"+key+"%' " : ' '}ORDER BY createTime DESC limit ${pg * size} , ${size}`
      return query(_sql)
    }

    const postDetail = (val) => { // 根据ID 查询 postsDetail
      let _sql = `SELECT * FROM posts WHERE id = '${val}'`
      return query(_sql)
    }

    const commentList = (val) => { // 获取留言列表
      let _sql = `SELECT * FROM comment WHERE postId = '${val}' ORDER BY createTime DESC`
      return query(_sql)
    }

    const createComment = (val) => { // 添加 留言
      let _sql = `INSERT INTO comment (userName, content, postId, avator, createTime) VALUES (?,?,?,?,?)`
      return query(_sql, val)
    }

    module.exports =  {
      insetUser,
      findUser,
      createPosts,
      postsList,
      updatePosts,
      updatePostsComment,
      updatePostsHot,
      postDetail,
      createComment,
      commentList
    }

编写 koa2 配置

在 koa2/app.js 进行编写 koa2 配置

// app.js

    const path = require('path')
    const Koa = require('koa2');
    const router = require('koa-router');
    var cors = require('koa-cors');
    const bodyParser = require('koa-bodyparser');
    const config = require('./config.js');
    const server = require('koa-static');
    const jwt = require('jsonwebtoken')

    require('./mysql.js');

    const app = new Koa();

    app.use(server(
      path.join(__dirname , './public')
    )) // 设置静态文件

    app.use(cors({
          origin: 'http://localhost:8080',  // 允许 loclhost:8080 访问
          exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
          maxAge: 5,
          credentials: true,
          allowMethods: ['GET', 'POST'],
          allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
      })
    ); // 设置跨域

    app.use(bodyParser({
      formLimit: '1mb'
    })) // ctx body 中间件

    app.use(require('./routers/signUp.js').routes()) // 注册
    app.use(require('./routers/signIn.js').routes()) // 登录

    app.use(require('./routers/createPosts.js').routes()) // 新建文章
    app.use(require('./routers/postsList.js').routes()) // 搜索文章
    app.use(require('./routers/postDetail.js').routes()) // 文章detail
    app.use(require('./routers/updatePosts.js').routes()) // 修改文章

    app.use(require('./routers/createComment.js').routes()) // 添加留言
    app.use(require('./routers/commentList.js').routes()) // 获取留言

    app.listen(config.port) // 监听端口

    console.log('listen in localhost:' + config.port)

分析登录注册

详细分析一下 登录 注册 登录 -> 有账号 -> 校验密码 -> 成功 -> 返回Token 登录 -> 没有账号 -> 注册 -> 判断是否有账号 -> 没有-> sql注册 ///////////////////-> 注册 -> 有账号 -> 去登录

注册<br/>

signUp.js

// signUp.js

const router = require('koa-router')();
const uuidV1 = require('uuid/v1'); // 生成13位 userId
const userModel = require('../mysql.js');
const fs = require('fs'); // 文件操作

// 注册
router.post('/signUp', async (ctx, next) => {
// post请求 从body中获取注册参数
  let user = {
    userName: ctx.request.body.userName,
    passWord: ctx.request.body.passWord,
    repeatPass: ctx.request.body.repeatPass,
    avator: ctx.request.body.avator
  }

  await userModel.findUser(user.userName).then(async (res) => {
    if (res.length) { // length > 1 说明 表中有数据
      try {
        throw Error('用户已存在')
      } catch (err) {
        console.log(err)
      }
      ctx.body = {
        state: 0,
        msg: '用户已存在!',
        data: []
      }
    } else if (!user.userName || user.passWord !== user.repeatPass) {
      ctx.body = {
        state: 0,
        msg: '密码输入错误',
        data: []
      }
    } else {  // 否者没有注册
      //处理上传头像
      let base64Data = user.avator.replace(/^data:image\/\w+;base64,/, "");
      let dataBuffer = new Buffer(base64Data, 'base64');
      let getName = Number(Math.random().toString().substr(3)).toString(36) + Date.now()

      // 上传图片到 public/images 文件夹中
      await fs.writeFile('./public/images/' + getName + '.png', dataBuffer, err => {
          if (err) {
            console.log(err);
            return false
          }
          console.log('头像上传成功') 
      });  

      await userModel.insetUser([uuidV1(), user.userName, user.passWord, getName, new Date().getTime()]).then((res) => {
        console.log('注册成功')
        ctx.body = {
          state: 1,
          msg: '注册成功',
          data: []
        }
      }).catch((err) => {
        ctx.body = {
          state: 0,
          msg: err,
          data: []
        }
      })
    }

  })

})

module.exports = router

登录 signIn.js

// signIn.js
let router = require('koa-router')();
let userModel = require('../mysql.js');

const createToken = require('../token/createToken.js');

router.post('/signIn',async (ctx, next) => {
  let user = {
    userName: ctx.request.body.userName,
    passWord: ctx.request.body.passWord
  }

  await userModel.findUser(user.userName).then((res) => {
    if (!res.length) {
      ctx.body = {
        state: 0,
        msg: '用户未注册!',
        data: []
      }
      console.log('用户未注册')
    } else {
      if (res[0].passWord === user.passWord) {
        let token = createToken(res[0]) // 创建token 存储用户id等重要信息

        ctx.body = {
          state: 1,
          msg: '用户登录成功!',
          data: [],
          token
        }
        console.log('密码校验正确, 允许登录')
      } else {
        ctx.body = {
          state: 0,
          msg: '用户名或者密码错误!',
          data: []
        }
        console.log('用户名或者密码错误')
      }
    }
  }).catch((err) => {
    ctx.body = {
      state: 0,
      msg: err,
      data: []
    }
  })

})

module.exports = router

生成Token, 解析Token

createToken.js , checkToken.js 原理

    // createToken.js
    const jwt = require('jsonwebtoken');

    // 创建token
    //登录时:核对用户名和密码成功后,应用将用户的id 作为JWT Payload的一个属性
    module.exports = function(user){

    // jwt.sign 参数详情
    //第一个是Payload,也就是用户信息(要注意payload不要传整个文档,Payload需要的是唯一且不变的数据,否则当Payload改变的时候需要重新下发token)。这里我们用文档的id,目的是唯一标识用户

    // 第二个参数是密钥,也就是你生成Signature时所用到的加密密钥。要注意这里必须和创建jwt的时候传入的secret一致,因为服务端需要用创建时的secret来解密。

    // 第三个参数则是设置一个token的过期时间,这里我们设置的是1天。

        const token = jwt.sign({
            userId: user.id,
            userName: user.userName,
            avator: user.avator
        }, 'kuaifengle', {    // "kuaifengle"  是校验码    解析时需要一致 才能取到 user 信息
            expiresIn: '24h' //过期时间设置为24h 格式有(s, m, h , day)。那么decode这个token的时候得到的过期时间为 : 创建token的时间 + 设置的值
        });
        return token;  返回token  前端存在浏览器cookie 中
    };
    //  checkToken.js
    const jwt = require('jsonwebtoken');

    // 接口访问必须要有Token (需要用户登录)
    module.exports = async ( ctx, next ) => {
        const authorization = ctx.get('Authorization'); // request 带过来的 token  存在浏览器的cookie中
        if (authorization == '') {
            ctx.body = {
                state: 0,
                msg: '用户未登录'
            }
            return false
        }
        const token = authorization;
        let tokenContent;
        try {
            // 根据 "kuaifengle" 钥解析 token 判断是否失效
            tokenContent = await jwt.verify(token, 'kuaifengle');     //如果token过期或验证失败,将抛出错误
            // 存入ctx 中 next() 可以获取到设置的 userInfo 数据
            ctx.userInfo = tokenContent
        } catch (err) {
            ctx.body = {
                state: 0,
                msg: '用户登录验证失效'
            }
        }
        await next();
    }

<br/>

其他的接口就不做解释了

项目打包后,放在 Koa2 / public / 下,就可以访问 localhost:3001 查看页面了

Github地址

都是基本的mysql语句操作,和业务逻辑, 具体看github源码

觉得对你有帮助的话,可以star一下 ^_^

原文链接:https://segmentfault.com/a/1190000015962701

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-37698.html

文章标题:全栈前端入门必看 koa2+mysql+vue+vant 构建简单版移动端博客

相关文章
Node.js 2014这一年发生了什么
Node.js 的 2014 年充满了不幸和争议. 这一年 Noder 们经历了太多的伤心事, 经历了漫长的等待, 经历了沉重的分裂之痛. 也许 Noder 们不想回忆14年 Node.js land 发生的事情, 但正因为痛才更有铭记的价...
2015-11-12
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
Angular2-primeNG文件上传模块FileUpload使用详解
近期在学习使用Angular2做小项目,期间用到很多primeNG的模块。 本系列将结合实战总结angular2-primeNG各个模块的使用经验。 文件上传模块FileUploadModule 首先要在使用该组件的模块内导入文件上传模块 ...
2017-03-09
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: &lt;template...
2017-03-13
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; ...
2017-03-13
破解前端面试(80% 应聘者不及格系列):从 闭包说起
不起眼的开始 招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结...
2017-06-02
前端交流QQ群
我们建立了一个前端交流QQ群供大家交流,有什么问题都可以在群里提问,欢迎你的加入,也希望我们大家能够在群里互帮互助,同时也能学到东西。 我们相信,前端有你更精彩! 为了让更多的小伙伴加入我们,欢迎大家转发扩散! 长按以上二维码加入我们 ...
2016-04-01
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
回到顶部