Vue2 使用 vue-cli-plugin-mock 本地模拟数据

369 阅读4分钟

Vue2 使用 vue-cli-plugin-mock 本地模拟数据

github.com/xuxihai123/…

安装

npm i -D vue-cli-plugin-mock

@/mock

写一个入口文件 ./mock/index.js

mock示例写法一

const mockMap = {
  'GET /api/user': {
    // obj
    id: 1,
    username: 'kenny',
    sex: 6,
  },
  'GET /api/user/list': [
    // array
    {
      id: 1,
      username: 'kenny',
      sex: 6,
    },
    {
      id: 2,
      username: 'kenny',
      sex: 6,
    },
  ],
  'POST /api/login/account': (req, res) => {
    // express router style
    const { password, username } = req.body;
    if (password === '888888' && username === 'admin') {
      return res.json({
        status: 'ok',
        code: 0,
        token: 'sdfsdfsdfdsf',
        data: {
          id: 1,
          username: 'kenny',
          sex: 6,
        },
      });
    } else {
      return res.json({
        status: 'error',
        code: 403,
      });
    }
  },
  'DELETE /api/user/:id': (req, res) => {
    console.log('---->', req.body);
    console.log('---->', req.params.id); // request params
    res.send({ status: 'ok', message: 'delete success!' });
  },
};
module.exports = mockMap;

示例写法二

module.exports = [
  {
    path: '/api/user',
    handler: (req, res) => {
      return res.json({ username: 'admin', sex: 5 });
    },
  },
  {
    path: '/api/list',
    handler: function (req, res) {
      let query = req.query || {};
      return res.json({
        limit: query.limit,
        offset: query.offset,
        list: [
          { username: 'admin1', sex: 1 },
          { username: 'admin2', sex: 0 },
        ],
      });
    },
  },
  {
    path: '/repos/hello',
    handler: (req, res) => {
      return res.json({ text: 'this is from mock server' });
    },
  },
  {
    path: '/api/userinfo/:id',
    handler: (req, res) => {
      return res.json({
        id: req.params.id,
        username: 'kenny',
      });
    },
  },
  {
    path: '/api/user/list/:id/:type',
    handler: (req, res) => {
      return res.json({
        id: req.params.id,
        type: req.params.type,
      });
    },
  },
  {
    path: '/api/login/account',
    method: 'post',
    handler: (req, res) => {
      const { password, username } = req.body;
      if (password === '888888' && username === 'admin') {
        return res.json({
          status: 'ok',
          code: 0,
          token: 'sdfsdfsdfdsf',
          data: {
            id: 1,
            username: 'kenny',
            sex: 6,
          },
        });
      } else {
        return res.json({ status: 'error', code: 403 });
      }
    },
  },
  {
    method: 'delete',
    path: '/api/user/:id',
    handler: (req, res) => {
      res.send({ status: 'ok', message: '删除成功!' });
    },
  },
];

在vue.config.js中添加

module.exports = {
  pluginOptions: {
    mock: { entry: './test/mock.js', debug: true },
  },
};

test mock with curl

➜  ~ curl -X GET http://127.0.0.1:4000/api/user
{"id":1,"username":"kenny","sex":6}
➜  ~ curl -X GET http://127.0.0.1:4000/api/user/list
[{"id":1,"username":"kenny","sex":6},{"id":2,"username":"kenny","sex":6}]
➜  ~ curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"username":"admin","password":"888888"}' http://127.0.0.1:4000/api/login/account
{"status":"ok","code":0,"token":"sdfsdfsdfdsf","data":{"id":1,"username":"kenny","sex":6}}
➜  ~ curl -X DELETE http://127.0.0.1:4000/api/user/88
{"status":"ok","message":"delete success!"}

项目实战

package.json中添加

"vue-cli-plugin-mock": "^1.0.2",

@/mock

image.png

方案一

自动注册

// src\mock\index.js
const Mock = require('mockjs')

export function param2Obj(url) {
    const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
    if (!search) {
        return {}
    }
    const obj = {}
    const searchArr = search.split('&')
    searchArr.forEach(v => {
        const index = v.indexOf('=')
        if (index !== -1) {
            const name = v.substring(0, index)
            const val = v.substring(index + 1, v.length)
            obj[name] = val
        }
    })
    return obj
}

function XHR2ExpressReqWrap(respond) {
    return function(options) {
        let result = null
        if (respond instanceof Function) {
            const { body, type, url } = options
            // https://expressjs.com/en/4x/api.html#req
            result = respond({
                method: type,
                body: JSON.parse(body),
                query: param2Obj(url)
            })
        } else {
            result = respond
        }
        return Mock.mock(result)
    }
}
const mocksContext = require.context('./modules/', true, /.js$/)
mocksContext.keys().forEach(file_name => {
    // 获取文件中的 default 模块
    const mocks = mocksContext(file_name)
    for (const mock of mocks) {
        Mock.mock(
            new RegExp(`${process.env.VUE_APP_API_ROOT}mock/${mock.url}`),
            mock.type || 'get',
            XHR2ExpressReqWrap(mock.result)
        )
    }
})

mock数据

// src\mock\modules\login.js
module.exports = [
  {
    url: '/v1/user/login',
    type: 'post',
    result: option => {
      return {
        msg: '',
        code: '0',
        data: {
          userName: option.body.userName,
          token: 'eyJhbGciOiJIUzUxMiJ9EwLW48EL5ijVqcjFFuN9n3V2K3N-jU5L-_zjnLLHTQpfTY9Tjg',
          failure_time: Date.parse(new Date()) / 1000 + 24 * 60 * 60
        }
      };
    }
  },
  {
    url: '/v1/user/query',
    type: 'get',
    result: option => {
      let userList = [];
      if (option.query.isSelf === 0) {
        const user = {
          id: 650000201109297300,
          userName: 'Donna Miller',
          cnName: '韩明',
          email: 'r.codqydjldp@jjxn.td',
          phone: 'sunt ut enim et cupidatat',
          userLevel: 2,
          deptId: 5551652833778924,
          createdAt: '2004-08-31 00:07:01',
          updatedAt: '2022-07-20 04:12:28',
          deptPathName: 'dolore',
          deptName: '研究院',
          parentId: 3637678309766032,
          userId: 370000199909037950,
          hasChildren: 90371184.32199448,
          deptPathId: '4061621791721624'
        };
        userList.push(user);
      }
      return {
        msg: '查询成功',
        code: '0',
        data: userList
      };
    }
  },
  {
    url: 'member/permission',
    type: 'get',
    result: option => {
      let permissions = [];
      if (option.query.account == 'admin') {
        permissions = [
          'permission.browse',
          'permission.create',
          'permission.edit',
          'permission.remove'
        ];
      } else if (option.query.account == 'test') {
        permissions = ['permission.browse'];
      }
      return {
        msg: '',
        code: '0',
        data: {
          permissions
        }
      };
    }
  }
];

module.exports = [
  {
    url: '/v1/user/update',
    type: 'post',
    result: option => {
      return {
        msg: '修改成功',
        code: '0',
        data: {}
      };
    }
  },
  {
    url: '/v1/user/create',
    type: 'post',
    result: option => {
      return {
        msg: '新增成功',
        code: '0',
        data: {}
      };
    }
  },
  {
    url: '/v1/user/delete',
    type: 'post',
    result: option => {
      return {
        msg: '删除成功',
        code: '0',
        data: {}
      };
    }
  }
];

main.js中引入

import './mock'

方案二

自动注册

// src\mock\server.js
let mockMap = {}

const mocksContext = require.context('./server-modules/', false, /.js$/)
mocksContext.keys().forEach(file_name => {
    mockMap = Object.assign(mockMap, mocksContext(file_name).default)
})

export default mockMap

mock数据

// src\mock\server-modules\login.js
const Mock = require('mockjs');

export default {
  'POST /mock/v1/user/login': (req, res) => {
    return res.json(
      Mock.mock({
        msg: '',
        code: '0',
        data: {
          userName: req.body.userName,
          token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
          failure_time: Date.parse(new Date()) / 1000 + 24 * 60 * 60
        }
      })
    );
  },
  'GET /mock/member/permission': (req, res) => {
    let permissions = [];
    if (req.query.account == 'admin') {
      permissions = [
        'permission.browse',
        'permission.create',
        'permission.edit',
        'permission.remove'
      ];
    } else if (req.query.account == 'test') {
      permissions = ['permission.browse'];
    }
    return res.json({
      error: '',
      status: 1,
      data: {
        permissions
      }
    });
  }
};
// src\mock\server-modules\user.js
const Mock = require('mockjs');
Mock.Random.extend({
  phone: function () {
    var phonePrefixs = ['132', '135', '189'];
    return this.pick(phonePrefixs) + Mock.mock(/\d{8}/);
  }
});

export default {
  'POST /mock/v1/user/update': (req, res) => {
    return res.json(
      Mock.mock({
        msg: '修改成功',
        code: '0',
        data: {
          userName: req.body.userName,
          token: '@string',
          failure_time: Date.parse(new Date()) / 1000 + 24 * 60 * 60
        }
      })
    );
  },
  'POST /mock/v1/user/create': (req, res) => {
    return res.json(
      Mock.mock({
        msg: '新增成功',
        code: '0',
        data: {
          userName: req.body.userName,
          token: '@string',
          failure_time: Date.parse(new Date()) / 1000 + 24 * 60 * 60
        }
      })
    );
  },
  'POST /mock/v1/user/delete': (req, res) => {
    return res.json(
      Mock.mock({
        msg: '删除成功',
        code: '0',
        data: {}
      })
    );
  },
  'GET /mock/v1/user/query': (req, res) => {
    const list = [];
    if (req.query.isSelf == 1) {
      const currentUser = admin;
      list.push(currentUser);
    } else {
      for (let i = 0; i < 10; i++) {
        let user = {
          id: Mock.mock('@increment'),
          userName: Mock.Random.cname(),
          cnName: Mock.Random.cname(),
          email: Mock.Random.email('163.com'),
          phone: Mock.Random.phone(),
          userLevel: Mock.Random.integer(1, 2),
          deptId: Mock.Random.integer(1, 5),
          createdAt: Mock.Random.date('yyyy-MM-dd HH:mm:ss'),
          updatedAt: Mock.Random.date('yyyy-MM-dd HH:mm:ss'),
          deptPathName: Mock.Random.city(),
          deptName: Mock.Random.cname(),
          parentId: Mock.Random.integer(1, 10),
          userId: Mock.mock('@increment'),
          hasChildren: Mock.Random.integer(0, 1)
        };
        list.push(user);
      }
    }
    return res.json(
      Mock.mock({
        msg: '',
        code: '0',
        data: list
      })
    );
  }
};

const admin = {
  id: 3, //当前对象唯一id,用于前端构造树结构
  userName: 'admin', //为空,代表该组暂无组长
  cnName: '管理员',
  email: 'admin@163.com',
  phone: '15381086786',
  userLevel: 0,
  deptId: 1, //当前部门的id
  createdAt: '2022-04-19T08:00:22.684Z',
  updatedAt: '2022-04-22T05:50:47.708Z',
  deptPathName: '/根部门',
  deptName: '根部门',
  parentId: 2, //当前对象的父节点id,用于前端构造树结构
  userId: 3, //为null代表该组暂无组长
  hasChildren: 0
};

const leader = {
  id: 2, //当前对象唯一id,用于前端构造树结构
  userName: 'longmo', //为空,代表该组暂无组长
  cnName: '龙陌',
  email: 'longmo@163.com',
  phone: '15381086786',
  userLevel: 1,
  deptId: 1, //当前部门的id
  createdAt: '2022-04-19T08:00:22.684Z',
  updatedAt: '2022-04-22T05:50:47.708Z',
  deptPathName: '/根部门/测试/web前端组',
  deptName: 'web前端组',
  parentId: 2, //当前对象的父节点id,用于前端构造树结构
  userId: 2, //为null代表该组暂无组长
  hasChildren: 0
};

const member = {
  id: 3, //当前对象唯一id,用于前端构造树结构
  userName: 'zhangsan', //为空,代表该组暂无组长
  cnName: '张三',
  email: 'zhangsan@163.com',
  phone: '15381086786',
  userLevel: 2,
  deptId: 1, //当前部门的id
  createdAt: '2022-04-19T08:00:22.684Z',
  updatedAt: '2022-04-22T05:50:47.708Z',
  deptPathName: '/根部门/测试/web前端组',
  deptName: 'web前端组',
  parentId: 2, //当前对象的父节点id,用于前端构造树结构
  userId: 3, //为null代表该组暂无组长
  hasChildren: 0
};

vue.config.js中添加

    pluginOptions: {
        mock: {
            entry: './src/mock/server.js',
            debug: true,
            disable: true
        }
    },

注意 新添加的文件可能需要重启一下服务才能生效