關於vuex
的簡單理解在這篇文章中已經提過了,如何在vuex
中管理mock
數據呢。
這是效果界面,所用的數據是mock
模擬所得,使用vuex
的store
存儲管理模擬數據。
這是我的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>