Vuex 在state中存取數據 modules分模塊 (2018/11/28)


一、store是一個狀態管理工具 (vueX中只有唯一 一個store)
用途 :存數據 取數據 改數據
 
把需要共享的數據放在store里 不需要共享的數據還是放在組件里
 
從state中取出數據渲染到view層------>view層再通過action改變數據------>action在將數據存入state  (vuex的處理流程是一個單向的數據流  必須先發動動作才能夠改數據)
 
Vuex就是提供一個倉庫,Store倉庫里面放了很多對象。其中state就是數據源存放地,對應於與一般Vue對象里面的data(后面講到的actions和mutations對應於methods)。
在使用Vuex的時候通常會創建Store實例new Vuex.store({state,getters,mutations,actions})有很多子模塊的時候還會使用到modules。
總結,Store類就是存儲數據和管理數據方法的倉庫,實現方式是將數據和方法已對象形式傳入其實例中。要注意一個應用或是項目中只能存在一個Store實例!!
      Vuex 的思想是 當我們在頁面上點擊一個按鈕,它會觸發(dispatch)一個action, action 隨后會執行(commit)一個mutation, mutation 立即會改變state,  state 改變以后,我們的頁面會state 獲取數據,頁面發生了變化。 Store 對象,包含了我們談到的所有內容,action, state, mutation,所以是核心了。
       store 對象注入到根實例后,在所有的子組件中,就可以用this.$store 來指向store 對象,獲取state。在子組件中,computed 屬性是根據它的依賴自動更新的。所以只要store中的state發生變化,它就會自動變化。
      通過computed屬性可以獲取到狀態值,但是組件中每一個屬性(如:count)都是函數,如果有10個,那么就要寫10個函數,且重復寫10遍return this.$store.state,不是很方便。vue 提供了 mapState 函數,它把state 直接映射到我們的組件中。
store就是一個實例其中存放了很多對象,每個對象又有不同的職責,有的存放數據,有的調用方法
 
建立新項目的步驟:
1、新建一個vue項目
2、把數據存到state里  在文件路徑下 cnpm i  vuex  --save
3、啟動項目  npm run dev
4、在src文件夾中新建一個文件夾  store---->index.js----->main.js引入store----->App.vue 取數據渲染到頁面上
index.js  (向store中存數據)
 
import  Vue from 'vue'   //引入兩個插件
import Vuex from 'vuex'
Vue.use(Vuex)
var store = new Vuex.Store({   //向store中存入數據
      state:{
            n:1000,
            age:12,
            lessions:["java","html"], //數組
            haha:{   //對象
                  yi:'mm'
            }
      }
})
export  default store  //將數據暴露出去
 
main.js
 
import Vue from 'vue'
import App from './App'
import router from './router'
import store from '@/store/index'   //引入index
Vue.config.productionTip = false
 
new Vue({
  el: '#app',
  router,
  store,  //注冊
  components: {
      App
  },
  template: '<App/>'
})
 
App.vue  (從state中取數據)
 
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
    {{n}}   {{age}}  {{lessions}}  {{haha}}   <!--渲染數據-->
  </div>
</template>
<script>
export default {
  name: 'App',
  computed:{    //取數據
      n(){
            return this.$store.state.n
      },
      age(){
            return this.$store.state.age
      },
      lessions(){
            return this.$store.state.lessions[0]
      },
      haha(){
            return this.$store.state.haha["yi"]
      }
  }
}
</script>
 
二、getters計算屬性
         Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。
             Getter 接受 state 作為其第一個參數, 也可以接受其他 getter 作為第二個參數

通過屬性訪問

               Getter 會暴露為 store.getters 對象,你可以以屬性的形式訪問這些值
                注意:getter 在通過屬性訪問時是作為 Vue 的響應式系統的一部分緩存其中的。(會產生緩存)
store.getters.doneTodos 
 

通過方法訪問 

                 也可以通過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 里的數組進行查詢時非常有用。
                   注意,getter 在通過方法訪問時,每次都會去進行調用,而不會緩存結果。(不會產生緩存)
store.getters.getTodoById(2)
 
三、mutations 同步的方法更改數據
              更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。 唯一修改狀態的事件的回調函數
               mutation中放的是處理數據邏輯的方法,它能夠使數據和視圖分離,起到更改數據(狀態)的作用。
(1)mutation 同步更改數據
        每一個mutation都有一個字符串類型的事件類型(type)和回調函數(handler),先注冊事件type,當觸發響應類型的時候調用handler();
(2)payload   提交載荷
         簡單的理解就是往handler(state)中傳參handler(state,payload);一般是個對象。
          state      是存放數據的地方
          payload      相當於一個參數
(3)commit   調用mutation中的type
         可以在組件中使用 this.$store.commit.("type名") 提交 經過mutation操作后做出改動的數據
         commit是同步函數,而且只能是同步執行
 
 
四、actions 異步的方法更改數據
         Action 提交的是 mutation,而不是直接變更狀態。並且可以包含任何的異步操作。actions將mutations里面只能同步處里數據的方法變成了可以異步處理數據的方法。
           Action 函數接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調用context.commit來提交一個mutation(因為mutation中的type是通過 $store.commit方法被提交的,action中的mutation可以通過context.commit被提交 )
          在組件中使用this.$store.dispatch("xxx") 分發 action
 
總結一下就是 同步提交mutation用 this.$store.commit("mutation中的type名")
                     異步提交mutation用 context.commit("mutation中的type名",參數)
                     異步分發action用 this.$store.dispatch("action中的type名")
store/index.js
 
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
var store = new Vuex.Store({
     state://存數據
           n:10000,
           age:12,
           lesson:['aaaa','bbbbbb']
     },
     mutations:{ //同步的方法更改數據
     changeAge1(state,payload){   //type:changeAge1,handler的第一個參數是state;
           state.age=state.age+1  // 變更狀態
     },
     changeNum1(state,payload){   //  提交載荷 payload  簡單的理解就是往handler(state)中傳參handler(state,payload);一般是個對象。
           state.n+=payload   //這個payload相當於一個參數
     },
     addlesson(state,payload){
           state.lesson=state.lesson.concat(payload) //在已有課程之后拼接新的課程 payload接收到了從actions中的getlesson中甩出來的數據
     }
     },
     actions:  //異步的方法定義和調用數據
           getlesson(context){ //context是自帶的上下文對象
                axios.get("http://localhost:3000/lessons").then((res)=>{   //從data.json中獲取數據
                     context.commit("addlesson",res.data.map((item)=>item.lesson))   // 第一個參數用於調用mutation中的方法  第二個參數相當於是payload 是將從json中獲取到的值甩出去
                     
                })
           }
     }
})
export default store
 
App.vue
 
<template>
  <div id="app">
    <router-view/>
   {{age}}  <button @click='changeAge'>年齡</button>
     <button @click='changeNum(1)'>+</button>{{n}}<button  @click='changeNum(-1)'>-</button>
     <p v-for='item in lesson'>{{item}}</p>
     <button @click='getlesson'>添加數據</button>
   <!--渲染數據-->
  </div>
</template>
<script>
export default {
  name: 'App',
  computed:{  //取數據
     n(){
           return this.$store.state.n
     },
     age(){
           return this.$store.state.age
     },
     lesson(){
           return this.$store.state.lesson
     }
  },
  methods:{  //調用方法改變數據
     changeAge(){
           this.$store.commit("changeAge1")
  },
  changeNum(n){
     this.$store.commit("changeNum1",n)
  },
getlesson(){
     this.$store.dispatch("getlesson")
            }
        }
    }
</script>
 
五、modules分模塊
        由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。
            為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
操作步驟:
             在src文件目錄下新建一個store文件夾----->在store中新建一個index.js----->在store目錄下新建一個demo文件夾 ------>在demo中新建state.js 、mutation.js、action.js、getter.js文件----->在demo/index文件中引入以上幾個js文件,並將其暴露出去------>store/index 引入demo文件夾並且創建store實例 引入modules----->App.vue中調用方法----->main.js引入store中的index.js  注冊store
                
state.js
export default{  //不需要寫state:{}
          n:1000,
          age:12,
          lesson:['math','english']
}
 
mutations.js
export default{
     
          changeAge(state,payload){
              state.age=state.age+1
          },
          changeNum(state,payload){
              state.n+=payload
          },
          addlesson(state,payload){
              state.lesson=state.lesson.concat(payload)
          }
     
}
 
actions.js
import axios from 'axios'
export default{
     
          getlesson(context){
               axios.get("http://localhost:3000/lessons").then((res)=>{
context.commit('addlesson',res.data.map((item)=>item.lesson))
              })
          }
     
}
 
demo/index.js
import state from './state'
import mutations from './mutations'
import actions from './actions'
export default{
     state,
     mutations,
     actions
}
 
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import demo from './demo'
Vue.use(Vuex)
var store = new Vuex.Store({  //創建store實例
     
     modules:{  //引入模塊
          demo
     }
     
})
export default store
 
App.vue
<template>
  <div id="app">
     <button @click='changeNum(1)'>+</button>{{n}}<button  @click='changeNum(-1)'>+</button>
     <button @click='changeAge'>改變年齡</button>{{age}}
    <p v-for='item in lesson'>{{item}}</p>
  <button @click='getlesson'>添加課程</button>
  </div>
</template>
<script>
export default {
  name: 'App',
  computed:{
     n(){
          return this.$store.state.demo.n  //注意路徑
     },
     age(){
          return this.$store.state.demo.age
     },
     lesson(){
          return this.$store.state.demo.lesson
     }
  },
  methods:{
     changeAge(){
          this.$store.commit('changeAge')
     },
     changeNum(inc){
          this.$store.commit('changeNum',inc)
     },
     getlesson(){
          this.$store.dispatch('getlesson')
     }
  }
}
</script>
 
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from '@/store/index'
Vue.config.productionTip = false
 
new Vue({
  el: '#app',
  router,  //把router和store放在實例上
  store,
  components: { App },
  template: '<App/>'
})
六、四個輔助函數
 
mapstate      //將state中的數據映射到組件中去
mapmutations
mapactions
mapgetters
<template>
    <div>
        {{Counter.arr[idx]}}<button @click="inc(idx)">+</button>
    </div>
</template>
 
import {mapState,mapMutations} from ‘vuex’   //引入
 
computed:{
props:["idx"],
...mapState(["counter","arr"])   //這表示counter中的arr
    },
mathods:{
    ...mapMutations(["inc"])
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM