2

如何在vuex中管理mock数据呢?

效果图
这是效果界面,所用的数据是mock模拟所得,使用vuexstore存储管理模拟数据。

这是我的store目录结构,分成几个模块,以其中planList模块为例进行讲解。
在这里插入图片描述

1.配置Vuex

modules文件夹中新建一个文件planList.js,然后在modules/index.js中导入


import planList from './planList'
const files = require.context('.', false, /\.js$/)
const modules = {
  planList // 模块名
}

files.keys().forEach(key => {
  if (key === './index.js') return
  modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})

export default modules

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
// const strict = process.env.NODE_ENV !== 'production'
const strict = false // 当为严格模式下时,一切的更改状态的动作都只能在mutation中进行,否则报错
Vue.use(Vuex)

export default new Vuex.Store({
  modules,
  strict: strict
})

然后在主文件main.js中引用:

import store from './store'

new Vue({
  components: {
    App
  },
  router,
  store,
  template: '<App/>'
}).$mount('#app')

2.Mock数据

在这里插入图片描述
关于如何mock数据可以去官网查看,这里只粘贴部分代码,不再多说

// data/planList.js
import Mock from 'mockjs'
const Random = Mock.Random
const List = []
const count = 300

for (let i = 0; i < count; i++) {
  List.push(Mock.mock({
    id: Random.integer(6000, 6999), // 编号
    airline: Random.string('upper', 2), // 航空公司
    flightNum: Random.string('upper', 2) + Random.integer(1000, 9999), // 航班号
    'cityCode|1': ['京', '津', '冀', '晋', '内蒙古', '辽', '吉', '黑', '沪', '苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤', '桂', '琼', '川', '贵', '云', '渝', '藏', '陕', '甘', '青', '宁', '新'], // 城市简码
    
  }))
}

export { List }

然后拦截数据,这里使用的是axios-mock-adapter,可以使用npm install axios-mock-adapter -D进行安装,然后在mock.js中引入:

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import { List } from './data/planList'

let _planList = List

export default {
  bootstrap () {
    let mock = new MockAdapter(axios)

    // mock success request
    mock.onGet('/success').reply(200, {
      msg: 'success'
    })

    // mock error request
    mock.onGet('/error').reply(500, {
      msg: 'failure'
    })
      
    // 获取列表(分页)
    mock.onGet('/flight/getListPage').reply(config => {
      let { page, pageSize, id } = config.params
      let mockList = _planList.filter(item => {
        if (id && item.name.indexOf(id) === -1) return false
        return true
      })
      let total = mockList.length
      mockList = mockList.filter((u, index) => index < pageSize * page && index >= pageSize * (page - 1))
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve([200, {
            total: total,
            list: mockList
          }])
        }, 1000)
      })
    })
  }
}

3.封装axios

新建一个api文件夹,建立request.js文件,封装请求。
在这里插入图片描述

import axios from 'axios'
import { Message } from 'element-ui'
import store from '../store'

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
// 创建axios实例
const instance = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 3000 // 请求超时时间
})
// request拦截器
instance.interceptors.request.use(config => {
  if (store.getters.token) {
    config.headers['X-Token'] = store.getters.token// 让每个请求携带自定义token 请根据实际情况自行修改
  }
  return config
}, error => {
  console.log(error) // for debug
  Promise.reject(error)
})

// 响应拦截器
instance.interceptors.response.use(
  response => {
  /**
  * code不是200时抛错 可结合自己业务进行修改
  */
    const res = response.data
    if (res.code !== 200) {
      Message({
        message: res.message,
        type: 'error',
        duration: 5 * 1000
      })

      return Promise.reject('error')
    } else {
      return response.data
    }
  },
  error => {
    console.log('err' + error)// for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default function (method, url, data = null) {
  method = method.toLowerCase()
  if (method === 'post') {
    return instance.post(url, data)
  } else if (method === 'get') {
    return instance.get(url, {
      params: data
    })
  } else if (method === 'delete') {
    return instance.delete(url, {
      params: data
    })
  } else if (method === 'put') {
    return instance.put(url, data)
  } else {
    console.error('未知的method' + method)
    return false
  }
}

然后在api.js中封装接口:

// import request from './request'
import axios from 'axios'

let baseURL = ''
// 获取计划列表
export const getPlanList = params => {
  return axios.get(`${baseURL}/flight/planList`, { params: params })
}

// 获取列表分页
export const getPlanListPage = params => {
  return axios.get(`${baseURL}/flight/getListPage`, { params: params })
}
// index.js中导入
import * as api from './api'

export default api

4.vuex中管理mock数据

modules/planList.js中调用接口,将获取到的mock数据保存在本地state中,然后组件中调用相应的数据进行渲染显示即可:

import { getPlanListPage } from '@/api/api' // 接口
import { GET_PLAN_LIST } from './mutation-type' // mutation类型常量化 在mutation-type.js中进行配置即可,也可以不用这样写,详情可见官方文档

export default {
  namespaced: true,// 启动命名空间
  state: {// 声明本地管理的状态
    list: {
      tableData: [],
      total: 0,
      currentPage: 1,
      pageSize: 20,
      listLoading: false,
      id: ''
    }
  },
  getters: {
    list: state => state.list
  },
  mutations: {
    [GET_PLAN_LIST]: state => {
      let para = {
        page: state.list.currentPage,
        pageSize: state.list.pageSize,
        id: state.list.id
      }
      state.list.listLoading = true
      getPlanListPage(para)
        .then(res => {
          console.log(res.data)
          // 将获取的数据保存在state中全局使用
          state.list.total = res.data.total
          state.list.tableData = res.data.list
          state.list.listLoading = false
        })
        .catch(error => {
          console.log(error)
        })
    }
  },
  actions: { // 异步响应
    getPlanList: context => {
      context.commit('GET_PLAN_LIST')
    }
  }
}

5.组件中获取状态

import { mapGetters, mapActions, mapMutations } from 'vuex'
mounted () {
    this.getPlanList() // 挂载
  },
  computed: {
    ...mapGetters('planList', ['list'])
  },
  methods: {
    ...mapActions('planList', ['getPlanList']),
    ...mapMutations('planList', ['GET_PLAN_LIST']),
    // 显示每页多少条数据
    handleSizeChange (val) {
      this.list.pageSize = val
      this.list.currentPage = 1
      this.GET_PLAN_LIST()
    },
    // 当前页
    handleCurrentChange (val) {
      this.list.currentPage = val
      this.GET_PLAN_LIST()
    }
  }
<!-- 这里只粘贴了表格的代码 从list中调用数据-->
        <el-table 
          :data="list.tableData" 
          highlight-current-row 
          style="width: 100%;margin-bottom: 20px;"
          height="800px"
          v-loading="list.listLoading"
          size="medium"
          class="planListTable el-table__column-filter-trigger"
          @cell-dblclick="rowDbClick"
          >
          <!-- <el-input placeholder="搜索" v-model="filters" clearable></el-input> -->
          <el-table-column fixed type="index" align="center" min-width="50px"></el-table-column>
          <el-table-column fixed  label="编号" align="center" min-width="85" sortable resizable>
            <div slot-scope="scope" >
              <el-input size="small" v-model="scope.row.id" @change="handleEdit(scope.$index, scope.row)"></el-input>
              <span>{{scope.row.id}}</span>
            </div>
          </el-table-column>
          <el-table-column fixed prop="airline" label="航空公司" align="center" min-width="120" sortable resizable></el-table-column>
          <el-table-column fixed prop="flightNum" label="航班号" align="center" min-width="120" sortable resizable></el-table-column>
          <el-table-column prop="cityCode" label="城市简码" align="center" min-width="120" sortable resizable></el-table-column>
        </el-table>

        <el-col :span="24" class="">
          <el-pagination 
            background
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="list.currentPage"
            :page-sizes="[20, 50, 100]"
            :page-size="list.pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="list.total"
            style="float:right;"
            >
          </el-pagination>

sueRimn
190 声望34 粉丝

做人嘛,最重要的就是开心