Vuex詳解


我們總以為,是生活欠我們一個“滿意”,其實是我們欠生活一個“努力”。
你好,我是夢陽辰!期待與你相遇!

01.Vuex概述

1.Vuex是做什么的?

官方解釋:Vuex是一個專為Vue.js 應用程序開發的狀態管理模式。

它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

Vuex也集成到Vue 的官方調試工具devtools extension,提供了諸如零配置的 time-travel調試、狀態快照導入導出等高級調試
功能。

2.狀態管理到底是什么?
狀態管理模式、集中式存儲管理這些名詞聽起來就非常高大上,讓人捉摸不透。

其實,你可以簡單的將其看成把需要多個組件共享的變量全部存儲在一個對象里面。

然后,將這個對象放在頂層的Vue實例中,讓其他組件可以使用。

那么,多個組件是不是就可以共享這個對象中的所有變量屬性了呢?

3.等等,如果是這樣的話,為什么官方還要專門出一個插件Vuex呢?難道我們不能自己封裝一個對象來管理嗎?

當然可以,只是我們要先想想VueJS帶給我們最大的便利是什么呢?

沒錯,就是響應式。
如果你自己封裝實現一個對象能不能保證它里面所有的屬性做到響應式呢?

當然也可以,只是自己封裝可能稍微麻煩一些。不用懷疑,Vuex就是為了提供這樣一個在多個組件間共享狀態的插件,用它就可以了。

4.Vuex管理哪些狀態呢?
有什么狀態時需要我們在多個組件間共享的呢?

如果你做過大型開放,你一定遇到過多個狀態,在多個界面間的共享問題。比如用戶的登錄狀態、用戶名稱、頭像、地理位置信息等等。
比如商品的收藏、購物車中的物品等等。

這些狀態信息,我們都可以放在統一的地方,對它進行保存和管理,而且它們還是響應式的。

02.單界面的狀態管理到多頁面狀態管理

在這里插入圖片描述
單頁面狀態管理,可以參照計數器這個案例。

多頁面狀態管理

多個頁面使用同一個狀態(變量)
Vue已經幫我們做好了單個界面的狀態管理,但是如果是多個界面呢?

多個試圖都依賴同一個狀態(一個狀態改了,多個界面需要進行更新)
不同界面的Actions都想修改同一個狀態(Home.vue需要修改,Profile.vue也需要修改這個狀態)
也就是說對於某些狀態(狀態1/狀態2/狀態3)來說只屬於我們某一個試圖,但是也有一些狀態(狀態a/狀態b/狀態c)屬於多個試圖共同想要維護的

狀態1/狀態2/狀態3你放在自己的房間中,你自己管理自己用,沒問題。

但是狀態a/狀態b/狀態c我們希望交給一個大管家來統─幫助我們管理! !!

沒錯,Vuex就是為我們提供這個大管家的工具。
全局單例模式(大管家)
我們現在要做的就是將共享的狀態抽取出來,交給我們的大管家,統一進行管理。

之后,你們每個試圖,按照我規定好的規定,進行訪問和修改等操作。

這就是Vuex背后的基本思想。

安裝Vuex(或者在創建項目的時候選擇安裝):

npm install vuex --save

在這里插入圖片描述
不要直接修改state,而是按上面的圖進行修改state,這樣瀏覽器就可以進行跟蹤。
瀏覽器插件,可以記錄每次修改,便與排錯。

Action可以進行異步操作。
練習:
App.vue

<template> <div id="nav"> <h3>App組件內容</h3> <p>{{$store.state.counter}}</p> <button @click="addition">+</button> <button @click="subtraction">-</button> <h3>---HelloWorld組件內容</h3> <hello-world></hello-world> </div> </template> <script> import HelloWorld from "./components/HelloWorld"; export default { name:'App', components:{ HelloWorld }, methods:{ addition(){ this.$store.commit('increment') }, subtraction(){ this.$store.commit('decrement') } } } </script> <style> </style> 

HelloWorld.vue

<template> <div> <p>{{$store.state.counter}}</p> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> 

store/index.js

import { createStore } from 'vuex' export default createStore({ state: { counter:1 }, mutations: { //方法 increment(state){ state.counter++ }, decrement(state){ state.counter--; } }, actions: { }, modules: { } }) 

在這里插入圖片描述

小結:
1.提取出一個公共的store對象,用於保存在多個組件中共享
的狀態

2.將store對象放置在new Vue對象中,這樣可以保證在所有的組件中都可以使用到

3.在其他組件中使用store對象中保存的狀態即可
通過this.$store.state.屬性的方式來訪問狀態

通過this.$store.commit(‘mutation中方法’)來修改狀態注意事項:
我們通過提交mutation的方式,而非直接改變
store.state.counter。

這是因為Vuex可以更明確的追蹤狀態的變化,所以不要直接
改變store.state.count的值。

state單一狀態樹
Vuex提出使用單—狀態樹,什么是單—狀態樹呢?
英文名稱是Single Source of Truth,也可以翻譯成單—數據源。

但是,它是什么呢?我們來看一個生活中的例子。

OK,我用一個生活中的例子做一個簡單的類比。
我們知道,在國內我們有很多的信息需要被記錄,比如上學時的個人檔案,工作后的社保記錄,公積金記錄,結婚后的婚姻信息,以
及其他相關的戶口、醫療、文憑、房產記錄等等(還有很多信息)。

這些信息被分散在很多地方進行管理,有一天你需要辦某個業務時(比如入戶某個城市),你會發現你需要到各個對應的工作地點去打印、蓋章各種資料信息,最后到一個地方提交證明你的信息無誤。

這種保存信息的方案,不僅僅低效,而且不方便管理,以及日后的維護也是一個龐大的工作(需要大量的各個部門的人力來維護,當
然國家目前已經在完善我們的這個系統了)。

這個和我們在應用開發中比較類似︰
如果你的狀態信息是保存到多個Store對象中的,那么之后的管理和維護等等都會變得特別困難.所以Vuex也使用了單—狀態樹來管理應瓜層級的全部狀態。

單一狀態樹(單一數據源)能夠讓我們最直接的方式找到某個狀態的片段,而且在之后的維護和調試過程中,也可以非常方便的管理和維護。

03.Getters基本使用

數據經過變化后:

store/index.js

 getters:{ powerCounter(){ return state.counter*state.counter }, over20stu(state){ return state.students.filter(s=>s.age<20) }, overAgestu(state){ return function (age) { return state.students.filter(s=>s.age>age) } } } 

App.vue

 <p>{{$store.getters.over20stu}}</p> <p>{{$store.getters.overAgestu(28)}}</p> 

04.mutations

Vuex的store狀態的更新唯一方式∶提交MutationMutation主要包括兩部分︰

字符串的事件類型( type )

一個回調函數(handler ) ,該回調函數的第一個參數就是state。
定義方式:

mutations: { //方法 increment(state){ state.counter++ }, decrement(state){ state.counter--; } }, 

通過mutation更新:

 addition(){ this.$store.commit('increment') } 

在通過mutation更新數據的時候,有可能我們希望攜帶一些額外的參數參數被稱為是mutation的載荷(Payload)

在這里插入圖片描述
但是如果參數不是一個呢?
比如我們有很多參數需要傳遞.
這個時候,我們通常會以對象的形式傳遞,也就是payload是一個對象.這個時候可以再從對象中取出相關的信息.
在這里插入圖片描述
特殊的提交方式:
在這里插入圖片描述
Mutation中的處理方式是將整個commit的對象作為payload使用,所以代碼沒有改變,依然如下:
單數payload為對象 即結果為object在這里插入圖片描述

Vuex的響應式原理

Vuex的store中的state是響應式的,當state中的數據發生改變時, Vue組件會自動更新.

這就要求我們必須遵守一些Vuex對應的規則:
提前在store中初始化好所需的屬性.

當給state中的對象添加新屬性時,使用下面的方式:
方式一:使用Vue.set(obj, ‘newProp’,123)

方式二:用新對象給舊對象重新賦值

在這里插入圖片描述

mutation常量類型

在mutation中,我們定義了很多事件類型(也就是其中的方法名稱).
當我們的項目增大時,Vuex管理的狀態越來越多,需要更新狀態的情況越來越多,那么意味着Mutation中的方法越來越多.

方法過多,使用者需要花費大量的經歷去記住這些方法,甚至是多個文件間來回切換,查看方法名稱,甚至如果不是復制的時候,可能還會出現寫錯的情況.
在這里插入圖片描述

05.actions

通常情況下, Vuex要求我們Mutation中的方法必須是同步方法.

主要的原因是當我們使用devtools時,可以devtools可以幫助我們捕捉mutation的快照但是如果是異步操作,那么devtools將不能很好的追蹤這個操作什么時候會被完成.

所以不能在mutation中進行異步操作。

但是某些情況,我們確實希望在Vuex中進行一些異步操作,比如網絡請求,必然是異步的.這個時候怎么處理呢?

Action類似於Mutation,但是是用來代替Mutation進行異步操作的.


 import { createStore } from 'vuex' export default createStore({ state: { counter:1, students:[ {id:23,name:'mengyangchen',age:19}, {id:24,name:'mengyang',age:20}, {id:24,name:'meng',age:29}, ], info:{name:'夢陽辰',age:20} }, mutations: { //方法 increment(state){ state.counter++ }, decrement(state){ state.counter--; }, updateInfo1(state){ state.info.name='李四' } }, actions: { //context:上下文 updateInfo(context){ setTimeout(()=>{ context.commit('updateInfo1') },1000) } }, modules: { }, getters:{ powerCounter(){ return state.counter*state.counter }, over20stu(state){ return state.students.filter(s=>s.age<20) }, overAgestu(state){ return function (age) { return state.students.filter(s=>s.age>age) } } } }) 

app.vue

<template> <div id="nav"> <h3>App組件內容</h3> <p>{{$store.state.counter}}</p> <p>{{$store.getters.over20stu}}</p> <p>{{$store.getters.overAgestu(28)}}</p> <p>{{$store.state.info.name}}</p> <button @click="addition">+</button> <button @click="subtraction">-</button> <button @click="updateInfo2">更新</button> <h3>---HelloWorld組件內容</h3> <hello-world></hello-world> </div> </template> <script> import HelloWorld from "./components/HelloWorld"; export default { name:'App', components:{ HelloWorld }, methods:{ addition(){ this.$store.commit('increment') }, subtraction(){ this.$store.commit('decrement') }, updateInfo2() { this.$store.dispatch('updateInfo') } } } </script> <style> </style> 

store/index.js
在這里插入圖片描述
app.vue
在這里插入圖片描述

06.moudules

Module是模塊的意思,為什么在Vuex中我們要使用模塊呢?

Vue使用單—狀態樹,那么也意味着很多狀態都會交給Vuex來管理.

當應用變得非常復雜時,store對象就有可能變得相當臃腫.

為了解決這個問題,Vuex允許我們將store分割成模塊(Module),而每個模塊擁有自己的state、mutation、action、getters等

我們按照什么樣的方式來組織模塊呢?
在這里插入圖片描述
項目結構:
在這里插入圖片描述

Do one thing at a time, and do well.

在這里插入圖片描述

在這里插入圖片描述


免責聲明!

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



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