vuex是幹什麼的?

1、vuex是幹什麼的?

學習任何東西,必然繞不過去的一個話題,就是我們爲什麼要使用它,它解決了什麼問題?

vuex是基於vue框架的一個狀態管理庫。可以管理複雜應用的數據狀態,比如兄弟組件的通信、多層嵌套的組件的傳值等等。

vuex有這麼幾個核心概念——State、Getter、Mutation、Action、Module。

2、vuex的“hello world”示例

由於數據狀態在多個組件維護的困難性,vuex在維護數據狀態的時候,使用的方法就是對一個“容器”進行維護。這個容器是一個狀態數,用對象的方式來表示。

(1)、store

const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            increment (state) {
                state.count++
            },
            decrement (state) {
                state.count--
            }
        }
    })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

store是vuex的核心對象,它記錄了整個vue應用的數據狀態以及操作數據的方式。

(2)、state

state就是store操作的數據狀態對象。

(3)、mutation

mutation提供了一種簡單易用的同步的方式改變state的狀態。

完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuex學習</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script src="https://unpkg.com/vuex"></script>
</head>
<body>
<div id="app">
    <p>{{ count }}</p>
    <p>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
    </p>
</div>
</body>
<script>
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            increment (state) {
                state.count++
            },
            decrement (state) {
                state.count--
            }
        }
    })

    new Vue({
        el:'#app',
        store,
        computed:{
            count(){
                return store.state.count;
            }
        },
        methods:{
            increment(){
                store.commit('increment')
            },
            decrement () {
                store.commit('decrement')
            }
        }
    })
</script>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

3、State

是一個單一狀態樹,這個state中維護着整個應用的數據管理的核心對象。

(1)、通過計算屬性獲取state

computed計算屬性是獲取vuex狀態的最簡單的方式。(store.state.count)
state變化,計算屬性會重新獲取state中變化的值。

const Counter = {
    template:"<span>{{count}}</span>",
    computed:{
        count(){ 
            return store.state.count//核心在這裏。
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(2)、把store的實例注入到每個子組件中

我們的需求,很多情況下要在不同的組件中引用store,我們可以跟組件中直接注入,然後就能在不同的子組件中獲取state。

var app = new Vue({
    el:'#app',
    store:store//這裏就是注入store的地方
})
  • 1
  • 2
  • 3
  • 4

(3)、mapState——獲取多個state數據

由於計算屬性每次基本上只能獲取一個state中的變化。如果獲取多個,就要多個計算屬性來解決。這樣代碼就顯得冗餘。mapState就是用來解決這個問題。

mutations: mapState({
    //這是箭頭函數的方式
    count: state => state.count,
    //這是傳字符串的方式
    count: 'count',
    //如果要使用this,只能攜程函數的方式。
    countAdd(state){ 
        return this.add + state.count
    }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(4)、獲取多個state的混合寫法(計算屬性+mapState)

mutations:{
    count(){
        return store.state.count
    },
    ...mapState({ 其他state })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4、Getter

如果說state通過計算屬性獲取的數據,我們要經過一定的操作(比如排序),那麼在Getter中我們就可以提供這種操作。使得我們獲取的state達到我們的需求。

它的本質就是對state進行過濾

const store = new Vuex.Store({
    state:{ 
        todoList:[{ 
            id: 1,
            text: 'do something1',
            isDo: true
        },{ 
            id: 2,
            text: 'do something2',
            isDo: false
        }]
    },
    getters:{ 
        doneTodos: funciton(state){ 
            return state.todoList.map(item=>item.isDo == true)
        }
    }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(1)、獲取getter——store.getters

是getter對外暴露的數據讀取方式
如: store.getters.doneTodos獲取了過濾後的state

(2)、Getter 也可以接受其他 getter 作爲第二個參數

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(3)、mapGetters——獲取多個getters的方式

使用方式和mapState差不多

5、Mutation

這是vuex提供的唯一更改store的屬性。

(1)、定義一個帶有Mutation的store

const store = new Vuex.Store({
    state:{
        count: 0
    },
    mutations:{
        increment(state){ 
            state.count++
        }
    }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

觸發方式:store.commit(‘increment’)

通過這樣的方式,讓state中的數據改變。

(2)、提交載荷

意思就是在commit的時候,傳入額外的參數

store.commit('increment',{
    num: 10
})
  • 1
  • 2
  • 3

也可以是這樣:

store.commit({
    type: 'increment',
    num: 10
})
  • 1
  • 2
  • 3
  • 4

(3)、應該遵守的相應規則

第一、提前在你的 store 中初始化好所有所需屬性。

第二、當需要在對象上添加新屬性時,你應該:
Vue.set(obj, ‘newProp’, 123)
state.obj = { …state.obj, newProp: 123 }
//這兩種方式都是把對象obj更新。

6、Action

這個屬性的作用類似於Mutation,但是它提交的是mutation,而不是變更狀態。並且action可以包含任何異步狀態。

(1)、註冊action

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

actions中的函數的參數是context,這個context有commit、getter、state等屬性。

(2)、分發 Action

定義好了Action,就需要在JavaScript中觸發這個Action。我們通過dispatch來觸發。

store.dispatch('increment')
  • 1
// 以載荷形式分發
store.dispatch('incrementAsync', {
  amount: 10
})

// 以對象形式分發
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(3)、異步操作

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(4)、在組件中分發 Action

this.$store.dispatch('xxx') //分發 action
  • 1

7、module模塊組

隨着項目越來越大,我們定義的狀態會越來越多,這個時候,我們要對我們的狀態進行模塊劃分。而module就是來幹這樣的事情的。
第一步、定義模塊。

const moduleA = {
    state:{},
    getters:{
    },
    mutations:{},
    actions:{}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第二步、改變 Vuex.Stroe 的寫法。

store = new Vuex.Store({
    modules:{ a: moduleA }
})
  • 1
  • 2
  • 3

第三步、在頁面中的使用方式

<div>{{$store.state.a.count}}</div>
  • 1

如果想在頁面中使用computed直接獲取,可以這樣寫:

computed:{
    count(){
        return this.$store.state.a.count;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章