vuex 漸進式教程

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
複製代碼

1.初級使用方法

// 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.中級使用方法: modules 模塊化

state用法


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

mutations用法(使用mutations能夠修改state的值)


在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 不知道何時回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的。

Action 用法


在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。

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-…

相關文章
相關標籤/搜索