如果想要了解 mock 模拟数据的话, 请看这篇文章(https://www.cnblogs.com/tugenhua0707/p/9813122.html)
在实际应用场景中, 总感觉 mock 数据比较麻烦, 并且在 webpack3 中 mock 数据的代码在正式环境并不能自动移除掉, 导致正式环境有 mock 相对应的代码, 但是在 webpack4 中, 会使用 tree shaking 插件会自动移除掉未使用到的代码的, 想要了解 tree shaking(https://www.cnblogs.com/tugenhua0707/p/9671618.html), 请看这篇文章. 所以为了兼容 webpack 版本的话, 研究了一种新的方式来模拟后台接口数据, 使用 webpack 中的 devServer.before 这个配置即可, 详细请看如下介绍.
在讲解如何模拟数据之前, 我们来看下我目前整个项目架构如下:
- ### 目录结构如下:
- demo1 # 工程名
- | |--- dist # 打包后生成的目录文件
- | |--- node_modules # 所有的依赖包
- | |--- App
- | | |---index
- | | | |-- views # 存放所有 vue 页面文件
- | | | | |-- parent.vue # 父组件
- | | | | |-- child.vue # 子组件
- | | | | |-- index.vue
- | | | |-- components # 存放 vue 公用的组件
- | | | |-- JS # 存放 JS 文件的
- | | | |-- store # store 仓库
- | | | | |--- actions.JS
- | | | | |--- mutations.JS
- | | | | |--- state.JS
- | | | | |--- mutations-types.JS
- | | | | |--- index.JS
- | | | |-- App.JS # vue 入口配置文件
- | | | |-- router.JS # 路由配置文件
- | |--- views
- | | |-- index.HTML # HTML 文件
- | |--- JSON # 存放所有模拟数据
- | | |-- parent_getPower.JSON
- | | |-- parent_reConfig.JSON
- | | |-- parent_reconlist.JSON
- | | |-- parent_reGroup.JSON
- | |--- mock.JS # mock 数据的所有调用方法
- | |--- webpack.config.JS # webpack 配置文件
- | |--- .gitignore
- | |--- README.md
- | |--- package.JSON
- | |--- .babelrc # babel 转码文件
项目的结构如上所示: 其中 JSON 文件夹内会存放所有模拟的数据, 比如和开发后台约定好的数据, 我可以直接把数据复制到 JSON 文件内, 比如我们简单的看下 parent_reConfig.JSON 数据代码如下(假如开发接口返回的数据是这样的):
- {
- "data": [{
- "bTableName": "reconfig",
- "businessCode": "reconfig",
- "businessImportImpl": "reconfig",
- "businessImportMethod": "reconfig",
- "businessName": "reconfig"
- }
- ],
- "code": 0
- }
其他的 JSON 文件也是类似的数据, 这里不一一贴代码哦, 有兴趣的话, 可以到下面的 GitHub 上查看 demo.
JSON 文件命名方式: 比如我上面 JSON 下的叫 parent_reConfig.JSON, 因为 vue 页面叫 parent.vue, 所以前缀就是页面的名称, 然后下划线(_) + reConfig + 'json', 其中 reConfig 是接口的最后一个名字, 这样命名的话, 我一眼就可以知道是那个页面下的接口, 接口是做什么使用的. 方便以后接口很多更容易区分.
2. 在项目的根目录下 mock.JS 代码是如下所示:
- const getPower = require('./json/parent_getPower.json');
- const reConfig = require('./json/parent_reConfig.json');
- const reConList = require('./json/parent_reconlist.json');
- const reGroup = require('./json/parent_reGroup.json');
- function Mock(App) {
- App.get('/xxxx/yyy', function(req, res) {
- console.log('getPower111');
- res.JSON(getPower);
- });
- App.post('/reconfig', function(req, res) {
- console.log('reConfig111');
- res.JSON(reConfig);
- });
- App.post('/conlist', function(req, res) {
- console.log('reConList111');
- res.JSON(reConList);
- });
- App.post('/regroup', function(req, res) {
- console.log('reGroup111');
- res.JSON(reGroup);
- });
- }
- module.exports = Mock;
如上代码首先是把 JSON 文件夹下的所有的 JSON 文件 require 进来, 然后定义一个函数, 里面写所有的 (get 或 post) 方法, 然后使用 res.JSON 方式就可以把上面的 JSON 数据模拟返回回来. 如上的 App 参数是从 webpack.config.JS 配置传进来的.
3. webpack.config.JS 配置方式如下:
- // 引入 mock.JS
- const Mock = require('./mock.js');
- module.exports = {
- devServer: {
- port: 8082,
- host: '0.0.0.0',
- headers: {
- 'X-foo': '112233'
- },
- inline: true,
- overlay: true,
- stats: 'errors-only',
- before: function(App) {
- console.log(App);
- if (process.env.NODE_ENV === 'mock') {
- Mock(App);
- }
- }
- },
- plugins: [
- // 设置环境变量信息
- new webpack.DefinePlugin({
- 'process.env': {
- NODE_ENV: JSON.stringify(process.env.NODE_ENV)
- }
- })
- ]
- }
如上配置代码, 首先引入 mock.JS 进来, 上面的 mock.JS 对外返回函数, 因此在 devServer.before 中配置调用下 Mock 函数, 传入参数是 App, 并且环境变量也判断了下, 如果是 mock 环境, 就执行 mock 函数代码的数据, 否则不是 mock 命令的话, 就不会执行 mock 数据, 而是执行真正环境的数据. 下面我们来看下 上面 before 函数打印的 App 是什么东西, 如下所示:
- { [EventEmitter: App]
- domain: undefined,
- _events: { mount: [Function: onmount] },
- _maxListeners: undefined,
- setMaxListeners: [Function: setMaxListeners],
- getMaxListeners: [Function: getMaxListeners],
- emit: [Function: emit],
- addListener: [Function: addListener],
- on: [Function: addListener],
- prependListener: [Function: prependListener],
- once: [Function: once],
- prependOnceListener: [Function: prependOnceListener],
- removeListener: [Function: removeListener],
- removeAllListeners: [Function: removeAllListeners],
- listeners: [Function: listeners],
- listenerCount: [Function: listenerCount],
- eventNames: [Function: eventNames],
- init: [Function: init],
- defaultConfiguration: [Function: defaultConfiguration],
- lazyrouter: [Function: lazyrouter],
- handle: [Function: handle],
- use: [Function: use],
- route: [Function: route],
- engine: [Function: engine],
- param: [Function: param],
- set: [Function: set],
- path: [Function: path],
- enabled: [Function: enabled],
- disabled: [Function: disabled],
- enable: [Function: enable],
- disable: [Function: disable],
- acl: [Function],
- bind: [Function],
- checkout: [Function],
- connect: [Function],
- copy: [Function],
- delete: [Function],
- get: [Function],
- head: [Function],
- link: [Function],
- lock: [Function],
- 'm-search': [Function],
- merge: [Function],
- mkactivity: [Function],
- mkcalendar: [Function],
- mkcol: [Function],
- move: [Function],
- notify: [Function],
- options: [Function],
- patch: [Function],
- post: [Function],
- propfind: [Function],
- proppatch: [Function],
- purge: [Function],
- put: [Function],
- rebind: [Function],
- report: [Function],
- search: [Function],
- subscribe: [Function],
- trace: [Function],
- unbind: [Function],
- unlink: [Function],
- unlock: [Function],
- unsubscribe: [Function],
- all: [Function: all],
- del: [Function],
- render: [Function: render],
- listen: [Function: listen],
- request: IncomingMessage { App: [Circular] },
- response: ServerResponse { App: [Circular] },
- cache: {},
- engines: {},
- settings: {},
- _eventsCount: 1,
- locals:
- { settings: {}},
- mountpath: '/',
- _router: {}
- }
更多关于 devServer.before 可以看官网().
4. package.JSON 配置如下:
- {
- "scripts": {
- "dev": "cross-env NODE_ENV=development webpack-dev-server --progress --colors --devtool cheap-module-eval-source-map --hot --inline",
- "build": "cross-env NODE_ENV=production webpack --progress --colors --devtool cheap-module-source-map",
- "build:dll": "webpack --config webpack.dll.config.js",
- "start": "webpack-dev-server --progress --colors --devtool cheap-module-eval-source-map --hot --inline",
- "mock": "cross-env NODE_ENV=mock npm run start"
- },
- }
5. App/index/views/parent.vue 代码如下所示:
- <template>
- <div>
- </div>
- </template>
- <script type="text/javascript">
- import { mapActions } from 'vuex';
- export default {
- data() {
- return {
- }
- },
- created() {
- this.testMock();
- },
- methods: {
- testMock() {
- const obj = {
- 'xx': 11
- };
- // 请求的地址是 '//xxx.abc.com/xxxx/yyy'
- Promise.all([this.commonActionGet(['getPower', obj])]).then((res) => {
- console.log('getPower');
- console.log(typeof res);
- console.log(res);
- });
- Promise.all([this.commonActionPost(['reConfig', obj])]).then((res) => {
- console.log('reConfig');
- console.log(res);
- });
- Promise.all([this.commonActionPost(['reConList', obj])]).then((res) => {
- console.log('reConList');
- console.log(res);
- });
- Promise.all([this.commonActionPost(['reGroup', obj])]).then((res) => {
- console.log('reGroup');
- console.log(res);
- });
- },
- ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON'])
- },
- mounted() {
- }
- }
- </script>
如上代码, 当我执行打包命令 NPM run mock 时, 就会调用 webpack 中的 devServer.before 函数, 该函数会判断当前的环境是否是 mock 命令, 如果是 mock 命令就执行 mock.JS 中的 Mock 函数, 然后会请求数据.
注意: 上面的请求数据是:'//0.0.0.0:8082/reconfig' 这样的, 这样就可以把 JSON/parent_reConfig.JSON 请求的数据返回回来, 但是我们真正的接口的前缀可能是 '//xxx.abc.com', 因此我们在配置所有的接口名称的时候, 接口域名的前缀我们可以定义一个变量, 然后传递进去. 比如我下面是这样定义的:
- // const prefix = '//xxx.abc.com'; // 真正的域名接口先注释掉
- const prefix = '//0.0.0.0:8082';
我们可以简单的判断下:
- let prefix;
- if (process.env.NODE_ENV === 'mock') {
- prefix = '//0.0.0.0:8082'; // 测试域名
- } else {
- prefix = '//xxx.abc.com'; // 正式域名
- }
- const url = prefix + '/reconfig';
类似上面这中形式, 因此当我们在页面上请求 this.$http.get(url); 的时候, 实际上在 mock 数据下请求的是 '//0.0.0.0:8082/reconfig' 这样的, 因此会直接被 devServer.before 中拦截到, 因此会返回我们的模拟上的数据, 但是在我们使用 NPM run dev 或 NPM run build 的时候, 我们需要把 //xxx.abc.com 这个真正的接口域名前缀打开,'//0.0.0.0:8082' 需要被注释掉. 就可以了, 其他的 vue 中的代码不需要做任何改动, 以前该怎么写, 现在也还是就那么写.
查看 GitHub 上的代码
来源: https://www.cnblogs.com/tugenhua0707/p/9846298.html