The furthest distance in the world is from Monday to Friday, Oh, BOSS I am so sleepy, I need to rest. Boss: Next time! According to Murphy’s Law, what people usually mean by “next time” is that You can take Monday off. Of course, this is not possible, our boss is not such a person, the boss will say nothing sleepy play ping-pang, ha ha ha ha, so have the company table tennis, I am also full of question?? , as for why today to ridicule, because today I passed by to see a long time unused table tennis table in that quietly quietly in that sleep, sleep how sweet ah, I want to and it together ha ha ha. Some people must ask a study blog every day to open a mess of things, then I don’t mention it, blog technology must be very serious ah, but the blogger is not serious people don’t know wow ha ha ha, ok without further ado, we talked about mongodb construction last article, This article will talk about vue + KOA2 + mongodb front-end small demo practice it

  1. Build the front landing page

    Say nothing about vue scaffolding, right? Go straight to a project structure, write a front-end landing page, without talking about the code

    / / the index of the router. Js
    import Vue from "vue";
    import VueRouter from "vue-router";
    import Login from '@/components/Login'
    Vue.use(VueRouter);
    const routes = [
      {
        path: "/login".name: "Login".component: Login
      },
      {
        path: "/register".name: "Register".component: Register
      }
    ];
    
    const router = new VueRouter({
      mode: "history".base: process.env.BASE_URL,
      routes
    });
    
    export default router;
    Copy the code
    // Login.vue <template> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" class="demo-ruleForm"> <div Class ="login_form_input" label=" user "style="margin-top: 58px; >< el-form-item prop="username"> <el-input V-model =" ruleform. username" placeholder=" placeholder "></el-input> </el-form-item> </div> <div class="login_form_input" label=" password "style="margin-bottom:7px; >< el-form-item prop="userpass"> <el-input type="password" V-model ="ruleForm.userpass" placeholder=" please input the user password" ></el-input>  </el-form-item> </div> <div class="login_btn"> <input class="login_submit" type="button" @click="submitForm('ruleForm')" value=" login "/> </div> </el-form> </template> <script> import axios from 'axios' export default { data() { return { ruleForm: { username: "", userpass: "" }, rules: { username: [ { required: true, message: "User name or mobile phone number ", trigger: "blur"},], userPass: [{required: true, message:" Please select active area ", trigger: "change"}, {min: 6, Max: 18, message: "length between 3 and 18 characters ", trigger: "blur"}]}}; }, methods: {async submitForm(formName) {this.$refs[formName].validate(valid => {if (valid) this.$api.login({ username:this.ruleForm.username, password:this.ruleForm.userpass }).then(res => { console.log(res); }).catch((err) => { console.log(err); }) } else { console.log("error submit!!" ); return false; }}); }}}; </script>Copy the code
  2. Secondary encapsulation of Axios

    As mentioned above, we usually use AXIOS to make requests directly in the component, so that when we need to change an interface, we need to go to the component to find it. Now we will wrap axios

    • The directory structure

      -src

      ​ — http

      ​ –api.js

      ​ –config.js

      ​ –index.js

      ​ –insterface.js

    • Config.js: Axios configuration

      export default {
          method:'post'.// Base URL prefix
          baseURL:'/api'.// Request information header
          headers: {'Content-Type':'application/json; charset=UTF-8'
          },
          / / parameters
          data: {},// Set the timeout period
          timeout:10000.// Indicates whether credentials are required for cross-domain requests
          withCredentilas:true.// 'responseType' indicates the data type of the server response, which can be 'arrayBuffer ', 'blob', 'document', 'json', 'text', 'stream'.
          responseType: 'json'.// default
      }
      Copy the code
    • Api.js: Encapsulation includes intercepting, processing data, and returning server information

      import axios from 'axios'
      import config from './config'  // Add the default configuration
      import qs from 'qs'  // Serialize the request data, depending on the server's requirements
      import { Message } from 'element-ui'
      import router from '. /.. /router'
      
      export default function $axios(options) {
          return new Promise((resolve, reject) = > {
              const instance = axios.create({
                  baseURL: config.baseURL,
                  headers: {},
                  transformRequest: [function (data) {
                      console.log(data)
                  }]
              })
      
              / / request interceptor
              instance.interceptors.request.use(
                  config= > {
                      Tip 1: At the beginning of a request, you can start a full-screen loading animation with vuex
      
                      // Tip2: the token can be combined with vuex or relocalStorage
      
                      // if (store.getter.token) {
                      Headers [' x-token '] = getToken() // Make each request carry the Token -- [' x-token '] is a user-defined key. Change the key based on the actual situation
                      // }else{
                      // Redirect to the login page
                      // }
                      // Tip3: according to the request method, serialize the passed parameters, according to the back-end requirements
      
                      if (config.method.toLocaleLowerCase() === 'post' || config.method.toLocaleLowerCase() === 'put' || config.method.toLocaleLowerCase() === 'delete') {
                          config.data = qs.stringify(config.data)
                      }
                      return config
                  },
                  error= > { // Do something with an error request (interface error, timeout, etc.)
                      // Tip: 4 Close LoAdding
                      console.log('request:', error);
                      // 1. Determine that the request timed out
                      if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout')! = = -1) {
                          console.log('The request has timed out based on the timeout you set/the actual request has timed out, you can add a timeout solution here')
                          // return service.request(originalRequest); For example, repeat the request once more
                      }
                      // 2. You need to redirect to the error page
                      const errorInfo = error.response;
                      console.log(errorInfo);
                      if (errorInfo) {
                          // Error = errorinfo.data // See promise.reject at the bottom of the page for details of the error
                          const errorStatus = errorInfo.status; // 404 403 500... Etc.
                          router.push({
                              path: `/error/${errorStatus}`})}return Promise.reject(error);   // On the other side of the call you can get the error message you want to return
                  })
      
              // Response interceptor
      
              instance.interceptors.response.use(
                  response= > {
                      let data;
                      / / ie 9 when the response data is undefined, so you need to use the response. The request. The responseText (string) after Stringify
                      if (response.data == undefined) {
                          data = response.request.responseText
                      } else {
                          data = response.data
                      }
      
                      // Do different processing and back-end conventions according to the code value returned
      
                      switch (data.code) {
                          case ' ':
      
                              break;
      
                          default:
                              break;
                      }
                      // If the code is not returned correctly and is logged in, an error is thrown
                      // const err = new Error(data.description)
                      // err.data = data
                      // err.response = response
                      // throw err
                      return data
                  },
                  error= > {
                      if (error && error.response) {
                          switch (error.response.status) {
                              case 400:
                                  error.message = 'Request error'
                                  break;
                              case 401:
                                  error.message = 'Not authorized, please log in'
                                  break;
                              case 403:
                                  error.message = 'Access denied'
                                  break;
                              case 404:
                                  error.message = 'Error requesting address:${error.response.config.url}`
                                  break;
                              case 408:
                                  error.message = 'Request timed out'
                                  break
      
                              case 500:
                                  error.message = 'Server internal error'
                                  break
      
                              case 501:
                                  error.message = 'Service not implemented'
                                  break
      
                              case 502:
                                  error.message = 'Gateway error'
                                  break
      
                              case 503:
                                  error.message = 'Service unavailable'
                                  break
      
                              case 504:
                                  error.message = 'Gateway timed out'
                                  break
      
                              case 505:
                                  error.message = 'HTTP version not supported '
                                  break
                              default:
                                  break; }}console.error(error)
                      // I'm using the Element UI prompt component here
                      Message.error(`ERROR: ${error}`)
                      return Promise.reject(error) // Return the error message returned by the interface})// Request processing executes the instance method
              instance(options)
                  .then((res) = > {
                      resolve(res)
                      return false
                  })
                  .catch((error) = > {
                      reject(error)
                  })
      
          })
      
      }
      Copy the code
    • Interface-. js: manages interfaces in a unified manner

      import axios from './api'  
      If the project is large, you can separate the URL into a file and divide the interface into different modules
       export const login = params= >{  // One of the interfaces
          return axios({
              url: '/mongotest'.method: 'get',
              params
          })
       }
       // Note the post request
       //const Register = params =>{
         // return axios({
              //url:'/users/register',
              //method:'POST',
              //data:params
          / /})
      / /}
      
       export default {
          login
       } 
      Copy the code
    • Add methods to Vue and mount them

      import apiList from './interface';
      const install  = Vue= >{
          if (install.installed) return ;
          install.installed = true;
          Object.defineProperties(Vue.prototype,{
              $api: {get(){
                      return apiList
                  }
              }
          })
      }
      export default install
      Copy the code
    • Main.js: Use to hang in

      import api from './http/index'
      Vue.use(api);
      Copy the code
    • Component

       this.$api.login({
         username:this.ruleForm.username,
         password:this.ruleForm.userpass
       }).then(res => {
         console.log(res);
       }).catch((err) => {
         console.log(err);
       })
      Copy the code
  3. Vue is a proxy for local debugging of cross-domain requests

    I’m going to be localhost:3000 on the server, localhost:3000 on the client. 3001 such request it must involve cross-domain problem, as the Chinese cabbage, I stuck here for half a day, so I use in koa koa – background cross-domain open cors, easily done, but I shaft, I would have to agent, I want to be with you into what ha ha ha ha, this is how electrocuting this is. Perform proxy proxy in vue.config.js. I’ve been working on this for a while. Config.js, baseURL:’/ API ‘, that’s it, and then write the interface directly as URL:’/ mongotest’.

    module.exports = {
        devServer: {
            // Run the address locally
            host: 'localhost'.// Local run port
            port: '3001'.// Proxy configuration
            proxy: {
                // The interface requested is localhost:3000/ API /XXX
                '/api': {   
                    target: 'http://localhost:3000/'.changeOrigin: true.ws: false.pathRewrite: {
                        '^/api': ' '
                    }
                }
            }
        }
    }
    Copy the code
  4. Login data token

    This piece is really considered for a long time maybe I am very vegetables, please big guy do not spray, but absolutely is very comprehensive, I must be a very detailed walk again.

    • First, the front-end login page sends the login request, and the background returns the token

        this.$api.Login({
          username:this.ruleForm.username,
          password:this.ruleForm.userpass
        }).then((res) = > {
          let loginType = ' ';
          console.log(res);
          if (res.code===200) {
            // Store the token after login
            //localStorage.setItem('USER_TOKEN', JSON.stringify(res.token));
            (res.token)&&(this.$store.commit('setUserToken',res.token)); 
      
            // Store cookies for login status
            this.$cookie.setCookie({username:res.username},2/144);
            loginType ='success' ;
      
          }else{
            loginType ='error'; }}); }).catch((err) = > {
          console.log(err)
        })
      Copy the code
    • Background KOA to receive, talk about ideas, please send a short request, 1. Background needs to have an interface in the routing, 2. If you have an interface you’re going to compare username and password, right? You don’t need a nod. 3. Perform mongo query 4. Return the queried information

      // The interface receives data
      router.post('/login'.async function(ctx, next){
        //console.log(ctx.request.body);
        let {username, password} = ctx.request.body;
        if(! username || ! password)return ctx.body = {code: 4020.msg: 'Please fill in user name or password'};
      
        let args = {username, password};
        const userData = await getUsers.userLogin(args)
        ctx.body = userData
        console.log(userData);
        ctx.body = (userData.code === 200)? {code: 200.msg: 'Successful landing'.username:userData.username, token: jwt._createToken(userData)} 
           : userData
      })
      Copy the code
      You can't just type in a password and compare it, can you? We use Bcrypt for password encryption
      usersSchema.methods = {
          comparePassword: (_pass, password) = > { // Verify the method
              // _pass Pass password. Password is the password in the database
              return new Promise((res, rej) = > {
              bcrypt.compare(_pass, password, (err, isMath) = > { //compare the official method
                      if(! err) { res(isMath);// isMath returns true and false,true for validation
                      } else{ rej(err); }}); }); }};// call the password encryption method
       let result = await usersDoc.comparePassword(password, usersDoc.password).then((isMath) = > {
         if (isMath) { // Return true the account password exists
           return isMath
         } else { // Otherwise, the account has a password error
           console.log(isMath, "Password not found............");
         }
       }).catch((error) = > {
         console.log("The server is abnormal. Please restart the server......");
       });
      
      //console.log(result);
      return! result ? {code: -2 ,msg :'Incorrect password'}, {code:200._id: usersDoc._id,username: usersDoc.username,avatar: usersDoc.avatar, mobile: usersDoc.mobile,email: usersDoc.email}
      Copy the code
      // Mongo query using Mongoose, we create a new DB directory, need to have a mongose configuration file, data model file, contoller file, export call index file
      // The db directory structure is as follows:
      //	--index.js
      //	--db.js
      //	--models
      // --users.js
      //	--controllers
      // --user.js
      
      Copy the code
      // Config file db.js
      const mongoose = require('mongoose');
      / / the connection
      const DB_URL = 'mongodb://localhost:27017/msjx'
      mongoose.set('useCreateIndex'.true)
      mongoose.connect(DB_URL)
      
      mongoose.connection.on('connected'.function(){
          console.log('Connection successful' + DB_URL);
      })
      /** * link error Database link error */
      mongoose.connection.on('error'.function(err){
          console.log('Mongoose connection disconnected');
      })
      
      /** * Disconnected The connection is disconnected */
      mongoose.connection.on('disconnected'.function(){
          console.log('Link broken'+ DB_URL)
      })
      module.exports = mongoose 
      Copy the code
      // Model file
      const mongoose  =require('.. /db');
      const bcrypt  = require("bcrypt")
      const stringRandom = require('string-random');
      
      const { model ,Schema} = require('mongoose');
       // Define encryption password calculation strength
      const SALT_WORK_FACTOR = 10;
      const usersSchema = new Schema({
          username: {type:String.default:stringRandom(8),
              unique:true
          },
          alias_name:String.mobile: String.password: String.userType: Number.// User role
          school_type:String.email: String.family_name: String.reg_time: {type:Date.default:Date.now
          },
          avatar: {type:String.default:""}})// Save the previous action
      usersSchema.pre('save'.function(next) {
          var user = this;
          // Hash the password only when it has been changed (or new)
          if(! user.isModified('password')) return next();
          // Add salt
          bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
              if (err) return next(err);
              // Hash the password after the salted password
              bcrypt.hash(user.password, salt, function(err, hash) {
                  if (err) return next(err);
                  // Override the plaintext password with the hashed password
                  user.password = hash;
                  next();
              });
          });
      });
      usersSchema.methods = {
          comparePassword: (_pass, password) = > { // Verify the method
              // _pass Pass password. Password is the password in the database
              return new Promise((res, rej) = > {
              bcrypt.compare(_pass, password, (err, isMath) = > { //compare the official method
                      if(! err) { res(isMath);// isMath returns true and false,true for validation
                      } else{ rej(err); }}); }); }};const userModel  = model("users",usersSchema);
      module.exports = userModel
      Copy the code
      // control controls the model file
      const UsersModel  = require('. /.. /models/users');
      
      class UsersCtl {
          constructor(){
      
          }
          query () {  // User list query interface
              return new Promise((resolve,reject) = >{
                  UsersModel.find({},(err,res) = >{
                      if (err) {
                          reject(err)
                      }
                      resolve(res)  // res is a doc})})}async userLogin(obj) { // The user login method
              let {username,password}  = obj;
              
              const usersDoc = await UsersModel.findOne({"$or": [{'mobile':username} , {'username':username}]});
              if(! usersDoc) {return {
                     code:0.msg:"The user is not registered"}}let result = await usersDoc.comparePassword(password, usersDoc.password).then((isMath) = > {
                  if (isMath) { // Return true the account password exists
                      return isMath
                  } else { // Otherwise, the account has a password error
                      console.log(isMath, "Password not found............");
                  }
              }).catch((error) = > {
                console.log("The server is abnormal. Please restart the server......");
              });
              
              //console.log(result);
              return! result ? {code: -2 ,msg :'Incorrect password'}, {code:200._id: usersDoc._id,username: usersDoc.username,avatar: usersDoc.avatar, mobile: usersDoc.mobile,email: usersDoc.email}
          }
          async userRegister(obj) { // The user login method
              let {alias_name,password,mobile,school_type}  = obj;
              const usersDoc = await UsersModel.findOne({mobile});
              if (usersDoc) {
                  return {
                     code:0.msg:"The user is already registered"}}let userRegister = new UsersModel({alias_name,password,mobile,school_type});
              let userInfo = await userRegister.save();
              return {
                  code:200.msg:"Registration successful"}}save(obj){ 
              const m = new UsersModel(obj)
              return new Promise((resolve,reject) = >{
                  m.save((err,res) = >{
                      if (err) {
                          reject(err)
                      }
                      resolve(res)
                      //console.log(res)}}})})module.exports =  new UsersCtl()
      Copy the code
      // index.js file
      const UsersCtl  =require('./controllers/user')
      module.exports = {
          getUsers: UsersCtl
      }
      Copy the code
  5. Generate tokens separately

    // createToken
    const jwt = require('jsonwebtoken');
    const _createToken = (userInfo) = >{
        return jwt.sign({userInfo},'[email protected]', {expiresIn:'60'})}module.exports = {
        _createToken
    }
    Copy the code
    // checkToken
    const jwt =require('jsonwebtoken');
    const _checkToken = function (req,res,next){ // Get the token information in the request header file
        let token = req.body.token || req.query.token || req.headers['authorization'];
        console.log(token); 
    
        if (token) {
            // Verify that the token is correct
            let decoded = jwt.decode(token,'[email protected]');
            console.log(decoded,4444); // Verify that the token expires
            if (token && decode.exp<new Date(a) /1000) {
                return res.json({success:false.message:'Token has expired'})}else{
                returnnext(); }}else{  // If there is no token
            return res.status(403).send({
                success:false.message:'No token provided! '}}})module.exports = _checkToken;
    Copy the code

Please pay attention to my project github address