1. 程式人生 > 其它 >另一個雙向繫結machine---狀態機vuex

另一個雙向繫結machine---狀態機vuex

技術標籤:前端

前言

在對於一些要時常大量抓取適當已經請求過來的資料的系統,在路由的轉換中我們不想連著路由一起把資料倒來倒去,這個時候我們就需要一個可以存取大量資料的靜態儲存資料庫,這個東西就是我們要講到的-------狀態機Vuex

	官方說法:Vuex 是專門為 Vue.js 設計的狀態管理庫,它採用集中式儲存管理應用的所有元件的狀態。

原理

其實在原理上仍然是Vue的雙向響應式原理,根據這個框架本身對資料進行劫持和訂閱觀察,但是他的存取則是新的規則,有新的限制

	核心還是
	Object.defineProperty(obj,obj.attr,descriptor)
  引數: 
    obj
      要在其上定義屬性的物件。
    prop
      要定義或修改的屬性的名稱。

工具

工具作用
State用於資料的儲存,是store中的唯一資料來源
Getter類似於計算屬性,就是對State中的資料進行二次的處理,比如篩選和對多個數據進行求值等
Mutation類似事件,是改變Store中資料的唯一途徑,只能進行同步操作
Action類似Mutation,通過提交Mutation來改變資料,而不直接操作State,可以進行非同步操作
Module當業務複雜的時候,可以把store分成多個模組進行管理,便於維護

為專案配置狀態機

一般在專案中
在這裡插入圖片描述
基本上這個東西是這樣的

import Vue from "vue";
import Vuex from "vuex"
; //當然你要先npm下vuex啦 npm install vuex --save Vue.use(Vuex); //配置進vue裡 export default new Vuex.Store({ // 建立狀態機例項 state: { user: { userName: "", avtived: false } }, mutations: { setUser(state, data) { state.user.userName = data.userName; state.user.avtived =
data.avtived; } }, actions: { setUser({ commit }, data) { // 模擬非同步處理 setTimeout(() => { commit("setUser", data); }, 3000); } }, getters: { getUser(state) { return state.user; } } });

運用

State(其實你可以認為是Vue例項或者其中一個元件的data)

在元件中,通常我們可以用計算屬性(computed)來獲取state狀態並進行處理
下面這個就可以遍歷出一個產品清單

<template>
  <div id="app">
     <h2>product-one</h2> 
     <ul>
       <li v-for="(item,index) in product" :key="index">
         <div class="name" v-text="item.name"></div>
         <div class="price" v-text="item.price"></div>
       </li>
     </ul>
  </div>
</template>
<script>

export default {
  components:{
  },
  data() {
    return {
        
    }
  },
  created(){
  },
  computed:{
    product(){
      return this.$store.state.product   //獲取狀態機中狀態
    }
  },
  watch:{
   
  },
  methods: {
    
  }
};

</script>
<style>
#app{
  padding: 1rem;
}
ul{
  list-style: none;
  padding: 0;
}
</style>


Getter(可以認為是vue例項或其中一個元件中的computed)

Vuex 允許我們在 store 中定義“getter”。就像計算屬性一樣,getter 的返回值會根據它的依賴被快取起來,且只有當它的依賴值發生了改變才會被重新計算。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    product:[
      {name:'apple', price: '2'},
      {name:'banana', price: '3'},
      {name:'pear', price: '4'},
      {name:'melon', price: '5'}
    ],
    count:0,
    str:'江西九江',
  },
  //Getter 接受 state 作為其第一個引數
  getters:{
    changeProduct: (state) => {
      return state.product.map(val => {
          return {
              name: '**' + val.name + '--',
              price: val.price*2
          }
      })
      return state.product
    }
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

Mutation(類似於methods但是隻能同步操作不支援非同步)

mutation 必須是同步函式,即是他不支援非同步,無法發起請求
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個引數

  mutations: {
    decrePrice(state){
      state.product.forEach(val => {
          val.price -= 1
      })
    }
  },

mutations就類似事件,子元件中用this.$store.commit(‘事件名’)來獲取

<template>
  <div id="app">
     <h2>product-two</h2> 
    <ul>
      <li v-for="(item,index) in product" :key="index">
        <div class="name">水果名:{{item.name}}</div>
        <div class="price">價格:{{item.price}}</div>
      </li>
    </ul>
  </div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
  components:{
  },
  data() {
    return {
      str:'中國'
    }
  },
  created(){
    this.decrePrice()
  },
  computed:{
  // 使用物件展開運算子將 getter 混入 computed 物件中
  ...mapGetters({
    product:'changeProduct'
  })
  },
  watch:{
   
  },
  methods: {
    decrePrice(){
      return this.$store.commit('decrePrice')
    }
  }
};

</script>

Action

類似於 mutation,不同在於:
(1)Action 提交的是 mutation,而不是直接變更狀態。
(2)Action 可以包含任意非同步操作
Action 函式接受一個與 store 例項具有相同方法和屬性的 context 物件,因此你可以呼叫 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters。
分發dispatch action
子元件中,用this.$store.dispatch(‘action的名字’)來獲取。

actions: {
    decrePriceAction(context){
      setTimeout(()=>{
          context.commit('decrePrice')
      }, 2000)
    }
  },

Module

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態

嚴格模式

開啟嚴格模式,僅需在建立 store 的時候傳入 strict: true:

const store = new Vuex.Store({
  // ...
  strict: true
})

在嚴格模式下,無論何時發生了狀態變更且不是由 mutation 函式引起的,將會丟擲錯誤。這能保證所有的狀態變更都能被除錯工具跟蹤到。
#開發環境與釋出環境
不要在釋出環境下啟用嚴格模式!嚴格模式會深度監測狀態樹來檢測不合規的狀態變更——請確保在釋出環境下關閉嚴格模式,以避免效能損失。