另一個雙向繫結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 函式引起的,將會丟擲錯誤。這能保證所有的狀態變更都能被除錯工具跟蹤到。
#開發環境與釋出環境
不要在釋出環境下啟用嚴格模式!嚴格模式會深度監測狀態樹來檢測不合規的狀態變更——請確保在釋出環境下關閉嚴格模式,以避免效能損失。