vuex 漸進式教程,從入門級帶你慢慢深刻使用vuex。vue
Vuex 是什麼?
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態, 並以相應 的規則保證狀態以一種可預測的方式發生變化。webpack
vuex官網:vuex.vuejs.org/zh/guide/git
安裝vue-cli:github
1.cnpm install -g vue-cli
2. vue init webpack vuex
複製代碼
安裝vuexweb
cnpm i vuex --save
複製代碼
// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex' // 引入vuex
Vue.config.productionTip = false
Vue.use(Vuex);
let store = new Vuex.Store({ // store 對象
state:{
count:0
}
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, //使用store,這能夠把 store 的實例注入全部的子組件
components: { App },
template: '<App/>'
})
複製代碼
此時能夠在組件中使用 this.$store.state.count
獲取store中state的值。如:vuex
// 在組件的computed中使用
computed:{
count(){
return this.$store.state.count;
}
}
複製代碼
想一想一下當項目比較大的時候數據繁瑣,若是按照上述方法使用vuex,當你打開main.js你看的到場景是比較混亂的,各類數據繁雜在一塊兒,不便於往後的維護。請看下一步:vue-cli
2.1 在main.js中刪除下述這部分代碼npm
let store = new Vuex.Store({ // store 對象
state:{
count:0
}
})
複製代碼
2.2. 在src目錄下新建store文件夾並在該文件夾下新建index.js文件。 在 store/index.js寫入:api
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
strict:true, // 開啓嚴格模式 確保state 中的數據只能 mutations 修改
state:{
count:0
}
})
export default store;
複製代碼
對應的main.js應該寫入:緩存
import store from './store'
複製代碼
寫到這裏,咱們在組件裏就能夠獲取到store裏的state的值了
2.3 爲了方便測試直接在HelloWorld.vue 中使用store
<template>
<div class="hello">
<h2>{{count}}</h2>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
computed:{
count(){
return this.$store.state.count;
}
}
}
</script>
複製代碼
不少時候我們要對state裏的值進行操做,在vuex提供了一個方法mutations
在sore\index.js寫入:
//
...
state:{
count:0
},
mutations:{ // 更改數據的方法
add(state){
state.count++
},
//提交載荷用法
// add(state,n){
// state.count += n
// },
sub(state){
state.count--
}
}
...
//
複製代碼
組件(HelloWorld.vue)中使用mutations裏對應的方法:
<template>
<div class="hello">
<button @click="add">+</button>
<h2>{{count}}</h2>
<button @click="sub">-</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
computed:{
count(){
return this.$store.state.count;
}
},
methods:{
add(){
this.$store.commit('add');
},
//提交載荷用法
// add(){
// this.$store.commit('add',10);
// },
//對象風格的提交方式
// store.commit({
// type: 'add',
// n: 10
// })
sub(){
this.$store.commit('sub');
}
}
}
</script>
複製代碼
此時就能夠對count進行修改了。
當你想異步操做的時候,因爲mutation必須是同步的這一點,此時不能採用mutation對state 進行修改。action派上用場了,action就是一個函數集合,在裏面怎麼操做均可以,只要最後觸發mutation 就能夠了。
註解mutation不能異步操做的緣由:
mutations: { add (state) { api.callAsyncMethod(() => { state.count++ }) } } 複製代碼
如今想象,咱們正在 debug 一個 app 而且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都須要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的異步函數中的回調讓這不可能完成:由於當 mutation 觸發的時候,回調函數尚未被調用,devtools 不知道何時回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的。
在sore\index.js寫入:
mutations:{ // 更改數據的方法
add(state){
state.count++
},
sub(state){
state.count--
}
},
++++
actions:{
add(context){ // context 與 store 實例具備相同方法和屬性(但不是store 實例)
setTimeout(()=>{
context.commit('add');
},1000)
}
}
++++
複製代碼
組件(HelloWorld.vue)中使用getters裏對應的方法:
<template>
<div class="hello">
<button @click="add">+</button>
++++
<button @click="add_action">action +</button>
++++
<h2>{{count}}</h2>
<button @click="sub">-</button>
<div>
test: {{doneTodos[0].text}} <br>
length: {{doneTodosLength}}
</div>
</div>
</template>
export default {
methods:{
add(){
this.$store.commit('add');
// console.log(this);
},
sub(){
this.$store.commit('sub');
},
++++
add_action(){
this.$store.dispatch('add');
}
++++
}
}
複製代碼
看到這裏有沒有想過當咱們使用state中某一個數據時,咱們只想用該數據中符合條件的數據。好比:
state:{
count:0,
todos: [
{ id: 1, text: 'text1--true', done: true },
{ id: 2, text: 'text2--false', done: false }
]
}
複製代碼
此時咱們只想獲取state.todos中done爲true的數據時咱們應該怎麼獲取?
可能會有如下兩種方案:
1.每一個在組件中首先獲取todos,而後使用filter方法過濾;
2.寫一個公共函數在每一個組件中調用如下;
若是用到todos中done爲true的組件不少,這兩種方法都是很不理想的。Vuex爲此爲咱們引入了一個方法Getter。
官方解釋:Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。
在sore\index.js寫入:
mutations:{ // 更改數據的方法
add(state){
state.count++
},
sub(state){
state.count--
}
},
+++
getters:{ // 用法相似組件中的 computed, 能夠認爲是store的計算屬性
doneTodos:state => { // Getter 接受 state 做爲其第一個參數:
return state.todos.filter(todo => todo.done) // -> [{ id: 1, text: 'text1--true', done: true }]
},
// Getter 也能夠接受其餘 getter 做爲第二個參數
doneTodosLength:(state,getters) => {
return getters.doneTodos.length // -> 1
},
+++
}
複製代碼
組件(HelloWorld.vue)中使用getters裏對應的方法:
<template>
<div class="hello">
<button @click="add">+</button>
<h2>{{count}}</h2>
<button @click="sub">-</button>
+++
<div>
test: {{doneTodos[0].text}} <br>
length: {{doneTodosLength}}
</div>
+++
</div>
</template>
<script>
export default {
//...
computed:{
+++
doneTodos(){
return this.$store.getters.doneTodos // -> [{ id: 1, text: 'text1--true', done: true }]
},
doneTodosLength(){
return this.$store.getters.doneTodosLength // -> 1
}
+++
}
}
</script>
複製代碼
本篇代碼地址:github.com/xioasa/vue-…