vue中使用mockjs模拟接口

效果图

安装

npm install mockjs --save  // 三选一就可以了
cnpm install mockjs --save
yarn add mockjs

新建mock目录

    mock目录下新建index.jsjson文件
在这里插入图片描述
    mock下的index文件,注意每改接口后都要重启才能生效

// 引入外部资源
const fs = require('fs')
const path = require('path')
const Mock = require('mockjs')

// 读取本地文件
function getJsonFile (filePath) {
  // 读取指定的json文件
  const json = fs.readFileSync(path.resolve(__dirname, filePath), 'utf-8')
  // 解析并返回
  return JSON.parse(json)
}

module.exports = function(app) {
  // 登录
  app.post('/login', (req, res) => {
    const users = getJsonFile('./users.json') // 响应时,返回 mock data的json数据
    res.json(Mock.mock(users)) // 将json传入 Mock.mock 方法中,生成的数据返回给浏览器
  })
  // 城市列表
  app.get('/citylist', (req, res) => {
    const city = getJsonFile('./city.json')
    res.json(Mock.mock(city))
  })
}

    mock下的users.json文件

{
  "status": true,
  "message": "登陆成功",
  "data": [
    {
      "id": 1,
      "username": "admin",
      "password": "123",
      "nickname": "半度℃"
    },
    {
      "id": 2,
      "username": "tom",
      "password": "123",
      "nickname": "Tom"
    }
  ]
}

新建api目录

    api目录下新建index.jsrequest.js文件
在这里插入图片描述
    api下的index.js文件

import request from './request';
export default {
  login(params) {
    return request.post('/login', params, {
      action: '登录'
    });
  },
  city(params) {
    return request.get('/citylist', {
      action: '获取城市列表',
      params
    });
  }
}

    api下的request.js文件,这里也是对 axios 的封装

import axios from 'axios';
import Vue from 'vue';
import store from '@/store/index'

// 取消请求(用于当没有 token 时,取消当前的请求,直到获取 token)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

// 过滤掉空字符串
function filterEmptyKey(params) {
  Object.keys(params).forEach(key => {
    if (
    	params[key] === null ||
    	params[key] === '' || 
    	params[key] === 'null' || 
    	params[key] === undefined
    ) {
      delete params[key];
    }
  });
}

// 环境的切换
let baseURL = null
if (process.env.NODE_ENV === 'development') {
  baseURL = 'http://localhost:8080';
} else if (process.env.NODE_ENV === 'debug') {
  baseURL = '';
} else if (process.env.NODE_ENV === 'production') {
  baseURL = 'http://bandu.com';
}

const service = axios.create({
  baseURL: baseURL,
  timeout: 30000,
  cancelToken: source.token
});

// 请求拦截
service.interceptors.request.use(
  (config) => {
    // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,
    // 不用每次请求都手动添加了
    // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
    const token = store.state.token;
    token && (config.headers.Authorization = token);
    if (config.method === 'post') {
      const params = {
        ...config.data
      };
      filterEmptyKey(params); // 过滤掉空字符串
      config.headers['Content-Type'] = 'application/json';
      config.data = params;
    } else if (config.method === 'get') {
      config.params = {
        _t: Date.parse(new Date()) / 1000,
        ...config.params
      };
      filterEmptyKey(config.params); // 过滤掉空字符串
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截
service.interceptors.response.use(
  (res) => {
    const { data, config } = res
    // 如果是下载文件则需要加上这一段类型判断
    if (config.responseType === 'blob') {
      return response
    }
    if (!data.status) {
      // 错误提醒
      let message = data.message ? data.message : '未知错误'
      Vue.prototype.$message({
        message: config.action + '失败:' + message,
        type: 'error'
      });
    }
    return Promise.resolve(data) || {};
  },
  (error) => {
    return Promise.reject(error);
  }
);

export default service;

配置 vue.config.js

    重点是在devServer里配置before,注意配置好之后一定要重启

// 配置目录别名
const path = require('path');
function resolve (dir) {
  return path.join(__dirname, dir)
}
module.exports = {
  publicPath: '/',
  // 输出文件目录
  outputDir: 'dist',
  // 静态资源目录 (js, css, img, fonts)
  assetsDir: 'assets',
  // 指定生成的 index.html 的输出路径
  indexPath: 'index.html',
  // lintOnSave:{ type:Boolean default:true } 是否使用eslint
  lintOnSave: true,
  // productionSourceMap:{ type:Bollean,default:true } 生产源映射
  // 如果不需要生产时的源映射,那么将此设置为 false 可以加速生产构建
  productionSourceMap: true,
  // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。
  // 如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来
  transpileDependencies: [],
  // alias 目录别名配置
  chainWebpack: (config) => {
    config.resolve.alias.set('@', resolve('src'))
  },
  css: {
    loaderOptions: {
      css: {
        // 这里的选项会传递给 css-loader
      },
      sass: {
        prependData: `@import "~@/assets/css/custom.scss";` // 全局引入 scss 变量, 不用可以去掉
      },
      postcss: {
        // 这里的选项会传递给 postcss-loader
      }
    }
  },
  // devServer: { type: Object } 3个属性 host, port, https, 它支持 webpack-dev-server 的所有选项
  devServer: {
    port: 8080,
    open: false, // 配置自动启动浏览器
    overlay: { // 浏览器 overlay 同时显示警告和错误
      warnings: true,
      errors: true
    },
    before: require('./public/mock') /** 重点是这里,一定不能忘记 **/
  },
  configureWebpack: {
    devtool: process.env.NODE_ENV === 'development' ? 'eval-source-map' : undefined,
    // 解决缓存问题
    output: {
      filename: `js/[name].${new Date().getTime()}.js`,
      chunkFilename: `js/[name].${new Date().getTime()}.js`
    }
  }
}

在组件中使用

<template>
  <div class="wrapper">
    <el-form :model="ruleForm" ref="ruleForm" :rules="rules" label-width="80px">
      <el-form-item prop="username" label="用户名">
        <el-input v-model="ruleForm.username"></el-input>
      </el-form-item>
      <el-form-item prop="password" label="密码">
        <el-input v-model="ruleForm.password"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button @click="resetForm('ruleForm')">重置</el-button>
        <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import loginApi from '@/api/index';
export default {
  data () {
    return {
      ruleForm: {
        username: '',
        password: ''
      },
      rules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: ['blur', 'change'] }
        ]
      }
    }
  },
  methods: {
    submitForm (formName) {
      const that = this
      this.$refs[formName].validate((valid) => {
        if (valid) {
          loginApi.login().then((res) => {
            const result = res.data ? res.data : []
            let flag = false
            for (var i = 0; i < result.length; i++) {
              if (
              result[i].username === that.ruleForm.username && 
              result[i].password === that.ruleForm.password
              ) {
                flag = true
                // 将符合条件的用户ID和昵称存储到本地
                sessionStorage.userId = result[i].id
                sessionStorage.nickname = result[i].nickname
              }
            }
            if (flag) {
              that.$router.push('/home/')
            }
          })
        }
      })
    },
    resetForm (formName) {
      this.$refs[formName].resetFields() // 重置用户名和密码
    }
  }
}
</script>

<style scoped>
.wrapper {
  width: 340px;
  border: 1px solid #cccccc;
  border-radius: 5px;
  padding: 50px;
  position: absolute;
  top: 200px;
  left: 50%;
  transform: translateX(-50%);
}
</style>
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半度℃温热

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值