Store的解耦:
官方提供的是將Vuex註冊在src/main.js下,但是爲了後來項目store的解藕,我們採取一步到位式配置,參考輝哥React教案中react+redux的設計模式。
1.修改主store.js
,用來集中管理主分支數據,其他分支數據通過import
注入
import Vue from 'vue' // 引入 vue
import Vuex from 'vuex' // 引入vuex
// 引入分支store
import table from '@/page/table/store.js'
// 使用Vuex
Vue.use(Vuex);
// 創建並導出Vuex實例
export default new Vuex.Store({
strict: true,
devtools: true,
plugins: [],
modules: {
table
}
});
2.在src
下創建 page
文件夾,用來存放各自路由組件,page
中一個文件夾對應一個路由(也就是對應一個頁面
3.按”2步驟“在page中創建若干子文件夾,文件夾由以下構成:
index.vue
images
( 存放靜態圖片資源service.js
( 處理數據異步接口store.js
( 管理組件自己的store
4.當我們創建完一個page
的index.vue
後一定要去/router
文件夾中的index.js
中註冊路由。
import Vue from 'vue'
import Router from 'vue-router'
// 註冊路由
import HelloWorld from '@/components/HelloWorld'
import Table from '@/page/table/index'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/Table',
name: 'Table',
component: Table
}]
})
5.在config
文件夾中創建的request.js
export const ip = 'http://127.0.0.1:8081';
export default function request(method, url, body, history) {
method = method.toUpperCase();
if (method === 'GET') {
//fetch的GET不允許有body,參數只能放在url中
body = undefined;
} else {
body = body && JSON.stringify(body);
}
return fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: body
}).then((res) => {
if (res.status === 401) {
history.push('/');
return Promise.reject('Unauthorized.');
} else {
return res.json();
}
});
}
export const get = url => request('GET', url);
export const post = (url, body) => request('POST', url, body);
6.修改service.js
// 只負責異步數據的export
// 相當於dva三大金剛service
import request from '@/../config/request'
import { ip } from '@/../config/request'
/*
* @Description: 獲取表單數據
* @param: getMessageAcount
* @return: message
*/
export async function get_table(params) {
let url = ip + '/web/user/rest/getMessageAcount'
return request("POST", url, {
cmd: 'getMessageAcount',
type: 'request',
request: {
description: params.description
}
})
}
7.修改page
目錄下分支store.js
// 引入service的異步接口
import { get_table } from './service.js'
// 初始化分支數據
const state = {
table: [ ]
}
// 在vuex中通過mutations更新store
const mutations = {
get_table_success(state, payload) {
// 相當於redux中更新reducer
state.table = payload;
},
get_table_failed() { }
}
const actions = {
// 異步請求await 需要加async ,相同於dva中的call
async get_async(context, payload) {
// 異步操作,等待service的返回值
const record = await get_table(payload);
if (record.response && record.response.res) {
// 後臺返回true的數據
let result = record.response.message;
// 括號內指向mutations內的方法
context.commit("get_table_success", result);
} else {
// 後臺返回false的數據
context.commit(" get_table_failed");
}
}
}
export default {
namespaced: true, // 聲明分模塊的store需要加上
state,
mutations,
actions
};
8.修改page
目錄中index.vue
<template>
<div class="hello">
<button v-on:click.stop="async_action()">異步請求</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {};
},
methods: {
async_action() {
// 括號參數分爲兩部分:
// 斜槓前爲對應的分支模塊,斜槓後爲分支模塊對應的actions
// 格式:模塊名/模塊中的mutations
// 同樣可以攜帶參數
let description = "這是參數";
this.$store.dispatch("table/get_async", description);
}
}
};
</script>
9.此時通過按鈕點擊已經完成了異步數據的獲取以及更新到了store
,接下來是如何進行頁面渲染,在vuex
中有一個類似於 mapDispatchToState
的方法叫做 mapState
, 下面是使用方法:
...mapState({
a: "a"
}),
...mapState({
_state: state => state
}), // 捕獲外部狀態 此時獲取的是完整的store
...mapState(["test"]), // 抓取test分支模塊的完整數據
...mapState("test", ["isLogin”]) // 抓取test分支下的 “isLogin" 屬性
以上都是 mapState
的使用方法,但日常使用來說 後兩者使用度更高。
來讓我們接着完成index.vue
中的模塊
<template>
<div class="hello">
<button v-on:click.stop="async_action()">異步請求</button>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "HelloWorld",
data() {
return {};
},
methods: {
async_action() {
// 括號參數分爲兩部分,斜槓前爲對應的分支,斜槓後爲分支對應的actions
// 格式:模塊名/模塊中的mutations
// 同樣可以攜帶參數
let description = "這是參數";
this.$store.dispatch("table/get_async", description);
}
},
// 注入外部store 類似於connect
computed: {
...mapState(["table"])
// ...mapState(['x']), 可以注入多個不同模塊的store,根據實際情況注入
// ...mapState(['xx']),
// ...mapState(['xxx']),
}
};
</script>