Vue x
為vue.js應用程式開發的狀态管理模式
采用集中式存儲管理應用的所有元件狀态
以相應的規則保證以一種可預測的方式發生變化
應用場景
讀取,多個視圖依賴于同一個狀态
修改,不同視圖的行為需要改變同一個狀态
組成部分
State 資料倉庫
getter 擷取資料
Mutation 修改資料
Action 送出mutation
安裝Vuex
1、安裝vuex包:npm install vuex
2、建立執行個體:new Vuex.store()
3、在main.js中将vuex執行個體挂載到vue對象上
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
Vue.config.productionTip = false
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
}
})
new Vue({
store,
render: h => h(App),
}).$mount('#app')
count++示例
思路
1、state中建立count字段
2、mutations中建立一個count++的mutation
3、button新增click事件觸發mutation改變count
main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
Vue.config.productionTip = false
Vue.use(Vuex)
const store = new Vuex.Store({
// 狀态資料
state: {
count: 0
},
// 狀态改變方法
mutations: {
// 第一個參數是state, 可以接受第二個參數
increaseCount(state) {
state.count++;
}
}
})
new Vue({
store,
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
<h1>count: {{count}}</h1>
<button @click="increaseCount">點我++</button>
</div>
</template>
<script>
export default {
name: "app",
computed: {
count() {
// 擷取狀态資料
return this.$store.state.count;
}
},
methods: {
increaseCount() {
// 修改狀态資料
this.$store.commit("increaseCount");
}r
}
};
</script>
項目實戰
業務目标
1、制作一個需要賬号登入的課程學習項目
2、不同的課程需要不同的會員等級,實作購買會員的功能,課程分享
項目功能
1、通過state.userinfo控制使用者登入路由限制
2、多元件共享state.userStatus 和 state.vipLevel狀态
3、多元件修改state.userstatus 和 state.vipLevel狀态
檔案目錄樹
src
├── App.vue
├── main.js
├── router.js
├── store
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── mutations.js
│ └── state.js
└── views
├── Home.vue
└── Login.vue
檔案代碼
<template>
<div id="app">
<router-view/>
</div>
</template>
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
Vue.config.productionTip = false
// 前置守衛,權限校驗
router.beforeEach((to, from, next) => {
if (store.state.username || to.path === "/login") {
next()
} else {
next({
path: "/login"
})
}
})
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
component: () =>
import ('./views/Login.vue')
}
]
})
store/actions.js
export default {
buyVip({ commit }, username) {
return new Promise((resolve, reject) => {
// 模拟後端互動耗時
setTimeout(() => {
commit("setUserInfo", username)
resolve("購買成功")
}, 1000)
})
}
}
store/getters.js
export default {
getUserLevel(state) {
switch (state.username) {
case "admin":
return "管理者";
case "user":
return "會員";
default:
return "普通使用者"
}
}
}
store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
import state from './state'
import mutations from './mutations'
import getters from './getters'
import actions from './actions'
Vue.use(Vuex)
const store = new Vuex.Store({
state,
getters,
actions, // 異步操作
mutations // 同步操作
})
export default store
store/mutations.js
export default {
setUserInfo(state, username) {
state.username = username;
}
}
store/state.js
export default {
username: "",
password: ""
}
views/Home.vue
<template>
<div>
<h1>詳情頁</h1>
<p>歡迎登入:</p>
<p>{{this.$store.getters.getUserLevel}}</p>
<p>{{getUserLevel}}</p>
<p>{{this.$store.state.username }}</p>
<p>{{username}}</p>
<van-button type="primary" @click="byVip" size="large">購買會員</van-button>
</div>
</template>
<script>
import { mapGetters, mapState } from "vuex";
export default {
computed: {
// 解構
...mapGetters(["getUserLevel"]),
...mapState(["username"])
},
methods: {
byVip() {
this.$store.dispatch("buyVip", "user").then(res => {
this.$dialog.alert({
message: res
});
});
}
}
};
</script>
views/Login.vue
<template>
<div style="margin: 20px;">
<div style="text-align: center;background-color:#EEEEEE">
<h1>登入</h1>
</div>
<van-cell-group>
<van-field v-model="username" label="使用者名" placeholder="請輸入使用者名" required />
<van-field v-model="password" @keyup.enter.native="login" label="密碼" type="password" placeholder="請輸入密碼" required />
<div style="margin-top:30px">
<van-button type="primary" @click="login" size="large">登入</van-button>
</div>
</van-cell-group>
</div>
</template>
<script>
export default {
data() {
return {
username: "",
password: ""
};
},
methods: {
login() {
if (this.username !== "" && this.password !== "") {
this.$store.commit("setUserInfo", this.username);
this.$router.push({
path: "/"
});
} else {
this.$dialog.alert({
message: "登入失敗"
});
}
}
}
};
</script>