[手把手式教程,適合新手入門Vuex]-Vuex入門實踐(上)

做者:小土豆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

使用Vuex前須要先進行安裝,安裝命令:npm install vuex --save--dev

建立和訪問共享數據

使用Vuex建立全局共享數據

首先咱們先須要在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數據。

入口文件中配置Vuex

共享數據前面咱們已經建立好了,接着須要在入口文件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每次遞增1decrement方法約定共享數據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組件中的按鈕,成功的將counter1,且Index組件中的數據也自動更新;點擊Index組件中的按鈕,成功的將counter1App組件中的數據也自動更新。

異步修改數據

假設咱們前面的遞增遞減的需求變成:點擊按鈕後,過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&emsp; -->
<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.vueIndex.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.cnblogs.com/HouJiao/

掘金:juejin.im/user/58c61b…

簡書:www.jianshu.com/u/cb1c3884e…

微信公衆號:土豆媽的碎碎念(掃碼關注,一塊兒吸貓,一塊兒聽故事,一塊兒學習前端技術)

歡迎你們掃描微信二維碼進入羣聊討論(若二維碼失效可添加微信JEmbrace拉你進羣)

碼字不易,點贊鼓勵喲~

相關文章
相關標籤/搜索