做者:小土豆biubiubiujavascript
博客園:www.cnblogs.com/HouJiao/css
掘金:juejin.im/user/58c61b…html
簡書:www.jianshu.com/u/cb1c3884e…前端
微信公衆號:土豆媽的碎碎念(掃碼關注,一塊兒吸貓,一塊兒聽故事,一塊兒學習前端技術) vue
歡迎你們掃描微信二維碼進入羣聊討論(若二維碼失效可添加微信JEmbrace拉你進羣)碼字不易,點贊鼓勵喲~java
Vuex
被稱爲是專爲Vue
應用程序開發的的狀態管理模式。它的做用使用一句話描述就是:讓組件之間能夠共享數據
。webpack
話很少少,先拋開概念,咱們寫一個簡單的示例感覺一波。web
Vuex
入門實踐將分爲三篇,本篇是第一篇。vuex
項目開發環境搭建請移步做者的另一篇文章 新手入門vue-教你使用vue-cli搭建項目開發環境。vue-cli
本次的項目目錄以下:
使用Vuex
前須要先進行安裝,安裝命令:npm install vuex --save--dev
。
首先咱們先須要在E:\MyStudy\test\VueDemo\src\
目錄下新建一個目錄vuex
和文件store.js
。
接着在store.js
中使用Vuex
建立一個全局的共享數據。
// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 在state中建立一個全局共享的數據 counter
state: {
counter: 0
}
})
複製代碼
能夠看到使用Vuex
建立一個共享數據的語法也比較簡單,即在new Vuex.Store
中定義state
對象,在state
對象中就能夠建立全局的共享數據,本次咱們建立了一個counter
數據。
共享數據前面咱們已經建立好了,接着須要在入口文件main.js
中配置Vuex
,配置的步驟以下:
1.引入咱們編寫的關於Vuex的代碼模塊store.js
2.在根實例上配置Vuex
複製代碼
// E:\MyStudy\test\VueDemo\src\main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/router'
//1.引入vuex
import store from './vuex/store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
router: router,
// 2.根實例上配置vuex
store: store
})
複製代碼
前面咱們已經完成了兩件事:使用Vuex
建立共享數據counter
和配置Vuex
。
接着咱們就須要在組件中訪問這個共享數據counter
。
咱們先新建一個Index.vue
組件,在該組件中編寫訪問counter
的代碼。
<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
<div>
<h1>這裏是Index.vue組件</h1>
<h1>Index組件獲取共享數據:{{ $store.state.counter }}</h1>
</div>
</template>
<script> export default { name: 'Index' } </script>
複製代碼
訪問共享數據counter
的代碼爲:
<h1>Index組件獲取共享數據:{{ $store.state.counter }}</h1>
複製代碼
接着在App.vue
中編寫一樣的代碼訪問這個counter
,而且在App.vue
組件中將Index.vue
組件引入並展現。
<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<template>
<div id="app">
<img src="./assets/logo.png">
<!-- 獲取共享數據 -->
<h1>這裏是App組件</h1>
<h1> App組件獲取共享數據 : {{ $store.state.counter }} </h1>
<hr/>
<Index></Index>
</div>
</template>
<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>
<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
複製代碼
咱們分別在App.vue
組件和Index.vue
組件中訪問了共享數據counter
,如今咱們啓動項目在瀏覽器中看下結果。
App
組件和
Index
組件都可以訪問到
counter
的值。
到此,咱們簡單的建立一個共享數據而且在組件中成功的訪問到了這個共享數據,這裏咱們對Vuex
的使用步驟作一個小總結:
1.安裝vuex:npm install vuex
2.全局配置vuex:建立vuex實例,調用store方法配置在state中建立共享數據。
3.組件中使用$store.state.counter能夠訪問到共享數據
複製代碼
Vuex
中,假如須要改變共享數據,必須在Vuex
實例對象的Store
方法中約定這個變化。
咱們在store.js
中對counter
作兩個約束:遞增
和遞減
。
// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 在state中建立一個全局共享的數據 counter
state: {
counter: 0
},
mutations: {
// 遞增
increase(state) {
state.counter++
},
// 遞減
decrement(state) {
state.counter--
}
}
})
複製代碼
mutations
中的increase
方法就是約定共享數據counter
每次遞增1
;decrement
方法約定共享數據counter
每次遞減1
。
約束共享數據的變化已經完成了,接着就開始觸發這個變化從而使共享數據發生變化。
咱們在
App.vue
組件中觸發counter遞減
,在Index.vue
中觸發counter遞增
。
<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<template>
<div id="app">
<img src="./assets/logo.png">
<!-- 獲取共享數據 -->
<h1>這裏是App組件</h1>
<h1> App組件獲取共享數據 : {{ $store.state.counter }} </h1>
<button v-on:click="$store.commit('decrement')">點擊觸發共享數據counter遞減1</button>
<hr/>
<Index></Index>
</div>
</template>
<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>
<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
複製代碼
<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
<div>
<h1>這裏是Index.vue組件</h1>
<h1>Index組件獲取共享數據:{{ $store.state.counter }}</h1>
<button v-on:click="$store.commit('increase')">點擊該組件觸發共享數據counter遞增1</button>
</div>
</template>
<script> export default { name: 'Index' } </script>
複製代碼
能夠看到在組件中觸發共享數據counter
遞增和遞減的邏輯分別爲:$store.commit('increase')
和 $store.commit('decrement')
,
即便用$store.commit
方法並傳遞對應的函數名稱
。
能夠看到,點擊App
組件中的按鈕,成功的將counter
減1
,且Index
組件中的數據也自動更新;點擊Index
組件中的按鈕,成功的將counter
加1
,App
組件中的數據也自動更新。
假設咱們前面的遞增遞減的需求變成:點擊按鈕後,過3
秒再去修改counter
的值。那麼這個時候應該怎麼實現呢?
咱們直接上代碼。
// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 在state中建立一個全局共享的數據 counter
state: {
counter: 0
},
mutations: {
// 遞增
increase(state) {
state.counter++
},
// 遞減
decrement(state) {
state.counter--
}
},
actions: {
increaseAction(context){
setTimeout(function(){
context.commit('increase')
}, 3000);
},
decrementAction(context){
setTimeout(function(){
context.commit('decrement')
}, 3000);
}
}
})
複製代碼
在store.js
中,咱們把異步修改數據的邏輯定義在actions
中,而且經過提交mutations
改變共享數據的狀態。
那在組件中須要使用$store.dispatch
對應去觸發共享數據的改變。
下面咱們看一下組件中如何使用$store.dispatch
。
<!-- E:\MyStudy\test\VueDemo\src\App.vue  -->
<template>
<div id="app">
<img src="./assets/logo.png">
<!-- 獲取共享數據 -->
<h1>這裏是App組件</h1>
<h1> App組件獲取共享數據 : {{ $store.state.counter }} </h1>
<button v-on:click="$store.dispatch('decrement')">點擊等待3秒觸發共享數據counter遞減1</button>
<hr/>
<Index></Index>
</div>
</template>
<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>
<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
複製代碼
<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
<div>
<h1>這裏是Index.vue組件</h1>
<h1>Index組件獲取共享數據:{{ $store.state.counter }}</h1>
<button v-on:click="$store.dispatch('increase')">點擊等待3秒觸發共享數據counter遞增1</button>
</div>
</template>
<script> export default { name: 'Index' } </script>
複製代碼
最後,咱們在瀏覽器看下效果。
能夠看到,setTimeout
這個異步邏輯成功執行。
關於上面想要實現的異步
遞增和遞減,咱們的第一反應可能就是在mutations
中的遞增遞減函數添setTimeout
延遲執行函數,咱們來實踐一下。
App.vue
和Index.vue
不作任何修改,仍是前面的內容,只修改store.js
。
// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 在state中建立一個全局共享的數據 counter
state: {
counter: 0
},
mutations: {
// 遞增
increase(state) {
// 添加定時器執行
setTimeout(function(){
state.counter++
},3000);
},
// 遞減
decrement(state) {
//添加定時器
setTimeout(function(){
state.counter--
},3000);
}
}
})
複製代碼
瀏覽器看下結果:
能夠看到效果和actions
同樣!!!
沒辦法,我這人就是想多造做造做給你們看點不同的東西。
那對於mutations
官網確實有明確的說明,mutations
必須是同步函數。
mutations
必須是同步函數了。
緣由一:若是是異步函數,在觸發mutations的時候,瀏覽器的調試功能看不到數據的變化;
緣由二:mutations中異步函數中的數據變化沒法追蹤。
複製代碼
到這裏呢,咱們就不繼續往下探究了,由於基礎的尚未總結完,基礎總結完後在探究這個問題。
vue
組件中的計算屬性想必你們都知道,那麼Vuex
中共享數據的計算屬性的用途和原理也是同vue
組件中的計算屬性。
咱們假設vue
組件中須要對共享數據作一些其餘的轉換:將某個字符串進行翻轉,而且轉爲大寫。(這個場景項目中幾乎不會用到,僅僅爲了演示而編造的)。當多個組件都須要對某個共享數據作這樣的轉化時,想必寫起來也會比較繁瑣,所以Vuex
共享數據的計算屬性就幫了咱們解決這個問題。下面咱們使用Vuex
的共享數據的計算屬性來實現這個需求。
// E:\MyStudy\test\VueDemo\src\vuex\store.js
// 在該文件中已經將前面定義的counter刪除,從新定義了一個共享數據str
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 在state中建立一個全局共享的數據 str
state: {
str: 'hello'
},
getters: {
reverseAndToUpper(state){
return state.str.split("").reverse().join("");
}
}
})
複製代碼
關於共享數據的計算屬性的訪問,咱們只在App組件
中添加訪問代碼。
<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<!-- 在App組件中,將Index組件的引入代碼已經刪除 -->
<template>
<div id="app">
<img src="./assets/logo.png">
<!-- 獲取共享數據 -->
<h1>這裏是App組件</h1>
<h1> App組件獲取共享數據 : {{ $store.getters.reverseAndToUpper }} </h1>
</div>
</template>
<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>
<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
複製代碼
瀏覽器查看一下結果:
能夠看到,在App組件
中已經成功的訪問到了str
的計算屬性。
前面咱們一共實踐了Vuex
的這些內容:
1.在state中定義共享屬性,在組件中可以使用$store.state.屬性名訪問共享屬性。
2.在mutations可中定義修改共享數據的方法,在組件中可以使用$store.commit('方法名')同步修改共享屬性。
3.在actions中可定義異步修改共享數據的方法,在組件中可以使用$store.dispatch('方法名')異步修改共享屬性。
4.在getters中可定義共享數據的計算屬性,在組件中可以使用$store.getters.計算屬性名訪問共享數據的計算屬性。
複製代碼
那最後我在將文章最開始的圖拿過來。
根據咱們前面實踐的內容,你們能看懂這個狀態變化嗎?
做者:小土豆biubiubiu
簡書:www.jianshu.com/u/cb1c3884e…
微信公衆號:土豆媽的碎碎念(掃碼關注,一塊兒吸貓,一塊兒聽故事,一塊兒學習前端技術)
歡迎你們掃描微信二維碼進入羣聊討論(若二維碼失效可添加微信JEmbrace拉你進羣)碼字不易,點贊鼓勵喲~