Vuex入門

来源:https://www.cnblogs.com/karthuslorin/archive/2018/12/25/10169651.html
-Advertisement-
Play Games

在 開發中,組件通信一直是一大痛點。 當項目是很簡單的 或者多入口項目時,可以靠著 自帶的 進行組件通信;規模再大一些,可以搭配使用 匯流排進行兄弟組件通信;項目再大一些,出現更複雜的組件關係時,複雜的組件通信可以讓你寫得懷疑人生。 萬幸的是, 官方出品了 ,通過全局式的狀態管理,解決了這一痛點。 雖 ...


vue 開發中,組件通信一直是一大痛點。

當項目是很簡單的 SPA 或者多入口項目時,可以靠著 vue 自帶的 prop/$emit 進行組件通信;規模再大一些,可以搭配使用 bus 匯流排進行兄弟組件通信;項目再大一些,出現更複雜的組件關係時,複雜的組件通信可以讓你寫得懷疑人生。

萬幸的是, vue 官方出品了 vuex ,通過全局式的狀態管理,解決了這一痛點。

雖然 vuex 很好用,但是,很多小伙伴和我吐槽 vuex 的文檔和 vue-ssr 的文檔一樣,讓人看得一臉懵逼。

好吧,下麵就讓我來帶著大家一起入門 vuex

安裝並引入

正常情況下,我們使用 vue-cli3 生成項目時,可以選擇集成 vuex 到項目中。此時, vue-cli3 會自動安裝 vuex ,併在 src 文件夾下生成 store.js 完成 vuex 的引入和配置。

但是,很多同學並沒有使用 vue-cli3 或者生成項目時沒有選擇集成 vuex 。此時,就只能手動安裝並引入 vuex 了。

安裝

由於 vuex 是用於全局狀態管理的,所以,它不僅僅作用於開發環境,而且還要用於生產環境。

顯而易見,安裝 vuex 應該使用 -S--save 命令。

npm install vuex -S

引入

類似於 vue-cli3 生成的項目,我們在 src 文件夾下新建 store.js ,併在其中寫入:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({})

然後,我們只需要在 vue 實例中引入 store.js 中的 Vuex.Store 實例即可:

// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  // 引入store
  store,
  render: h => h(App)
}).$mount('#app')

Vuex的使用

完成了 vuex 的安裝和引入,接下來我們進入 Vuex 的使用。

vuex 中有三要素: statemutation 以及 action 。它們之間的關係可以用官網那張著名的圖來表示:

vuex

State

簡單來說, state 表示狀態,類似於 vue 中的 data (其實本質上就是差不多的, vuexvuebeforeCreate 鉤子中將 state 混入進 data)。但是,它們又有很大的不同: 在使用者看來, state 是全局的,這得益於 vuex 的設計理念——單一狀態樹。這些我將在後幾篇文章中詳細,現在我們只需要知道 state 是類似於全局下的 data

接下來我們通過一個簡單例子來感受下 state

首先,我們需要修改 store.js 文件,配置 state 。可以看到,我們在生成 Vuex.Store 實例時傳入了實例化選項對象,對象包含一個 state 屬性, state 對象的屬性就是我們定義的全局狀態。

此時,我們定義了一個全局狀態——count ,並將其的初始值設為1

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // 添加state
  state: {
    count: 1
  }
})

接下來,我們需要在組件中引用 count,由於它是全局狀態,我們可以在任何一個組件中使用。為了展示其威力,我們在兩個不同的組件中使用它。

首先我們在 App.vue 中使用它:

在模板中,我們使用 $store.state.count 引入該全局狀態,沒錯,使用它就是那麼簡單,只需要 以 $store.state.key 的形式調用。

// App.vue
<template>
  <div id="app">
    <div id="nav">
      {{$store.state.count}}
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

可以發現, Home 前多出了一個 1 ,這代表著我們成功引入了全局狀態 count

接下來我們在 Home.vue 的子組件 HelloWorld.vue 中引入 count

相同的引用方式: $store.state.count

// HelloWorld.vue
<template>
  <div class="hello">
    {{$store.state.count}}
  </div>
</template>

可以發現,頁面中又多出了一個 1 ,代表著我們又一次引用成功。現在,是不是已經感受到了 vuex 的威力?

Mutation

但是,上面的示例有個問題,那就是全局狀態是靜態的。如果在實際應用場景中,一般來說,會經常更改狀態。

有的同學會說,我們直接在方法中修改 this.$store.state.key 的值不就行了嗎?

不好意思,當然是不行的。

statedata 的另一大區別在於,你不能直接改變 state 。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用。

簡而言之,我們把 mutation 當做接收 state 作為參數並修改 state 的自定義事件即可,上一段所說的 commit 就是觸發 mutaion 這個自定義事件的方法。

光說不練假把式,接下來,我們對為 vuex 添加上 mutation ,實現 state 的動態改變:

首先,當然是修改生成 Vuex.Store 示例的選項對象,為其添加 mutations

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  // 添加mutation
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

在上面的代碼中,我們添加了一個名為 incrementmutation 。完成了自定義事件,接下來,我們只需要在組件中對 mutation 進行觸發即可。

我們在 HelloWorld.vue 添加一個按鈕,每次點擊觸發一次 increment 這個 mutation 。可以發現,觸發方式很簡單,只需要調用 store 自帶的 commit 方法,其中參數為需要觸發的 mutation 的名稱。

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.commit('increment')">修改count</button>
  </div>
</template>

點擊頁面中的按鈕,你會發現,頁面中的兩個 count 都同時增加了1,說明我們成功實現了 state 的動態修改。

Action

action 類似於 mutation ,也相當於一種自定義事件。只不過, action 操作的是 mutation 而不是 state

添加 action 的方法類似,在選項對象中新增 action 屬性即可。與 mutation 的參數不同, action 的參數就是當前創建的 Vue.store 對象實例的上下文,一般將其命名為 context 。我們需要使用其自帶的 commit 方法來觸發 mutation

下麵我通過實際的例子來嘗試下 action

首先,修改選項對象,使得新添加的 action 可以觸發之前的 mutation

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment ({ commit }) {
      commit('increment')
    }
  }
})

由於我們一般來說僅僅需要 context 中的 commit 方法,所以可以採用解構的方式,直接調用 commit 方法,而不需要以 context.commit 的方式使用它。

接下來,只需要修改 HelloWorld.vue ,使其能夠在點擊按鈕時觸發即可。

action 的觸發方式和 mutation 類似,只不過調用的方法是 dispatch

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.dispatch('increment')">修改count</button>
  </div>
</template>

點擊頁面按鈕,你會發現,實現了和之前相同的效果。

總結

學會了 vuex 三賤客: statemutationaction ,我們再回過頭看看前面的那張關係圖,此時應該很容易理解了吧?

組件交互觸發 action , 在 action 中進行非同步操作(可選)並觸發 mutationmutation 控制 state 的變動, state 修改之後,觸發響應式,重新渲染組件。

彩蛋

在官方文檔中,提到需要將非同步操作放入 action 中,而不能放在 mutation 中。實際上,在 mutation 中也可以進行非同步操作,而且也不會導致什麼奇怪的事情。

但是,既然官方文檔中這麼說了,我們在實際開發中,一般還是老老實實地將所有非同步操作放在 action 中。(猥瑣保平安 -_-)

另外,說了這麼多,其實在一些項目中,可以使用 provide/inject 代替 vuex 。具體的用法在此不再贅述,就當一個課後作業吧。

在項目中靈活使用 provide/inject ,有時可以起到出乎意料的作用哦。

最後的最後

篇幅有限,所以該篇文章只講述了 vuex 三賤客的基本用法,其他的進階用法,如: gettermodule , 簡寫以及 vuex 項目結構優化,甚至 vuex 源碼解析將會在之後的文章一一講解。

如果您覺得這片文章不錯的話,不如給我的 gayhub 點個star再走唄。

這個項目個人認為對很多新手在實際開發中使用 vuex 還是很有啟發和幫助的(手動狗頭)。

歡迎交流,謝謝~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在安裝資料庫軟體時出現以下情況: 解決方法一: 查看 less /uu/oraInventory/ContentsXML/inventory.xml文件,文件內容如下: <?xml version="1.0" standalone="yes" ?><!-- Copyright (c) 1999, 2 ...
  • 一.概述 Redis集群提供了分散式資料庫方案,集群通過分片來進行數據共用,並提供複製和故障轉移功能。在大數據量方面的高可用方案,cluster集群比Sentinel有優勢。但Redis集群並不支持處理多個keys的命令,因為這需要在不同的節點間移動數據,而達不到像Redis那樣的性能,在高負載的情 ...
  • 本文由雲+社區發表 作者介紹:簡懷兵,騰訊雲資料庫高級工程師,負責騰訊雲CDB內核及基礎設施建設;先後供職於Thomson Reuters和YY等公司,PTimeDB作者,曾獲一項發明專利;從事MySQL內核開發工作8年,具有豐富的優化經驗;在分散式存儲等領域有較豐富經驗。 MYSQL資料庫適用場景 ...
  • 資料庫伺服器(Virtual Machine)所在的Nutanix一臺主機由於故障,VM自動切換到另一臺主機,切換過程中VM會重新啟動,但是早上檢查的時候,發現點擊SQL Server Configuration Manager進去時報如下錯誤: ”Cannot connect to WMI pro... ...
  • 一、 背景 隨著業務的發展,線上Redis的數據越來越多,所以必須考慮擴容的事情了。對於redis的擴容,目前可選的方案有三種:1、client自己做sharding,一般是按key的hash值取模,對應到指定的redis server;2、採用redis3以上版本自帶的cluster;3、Twit ...
  • ``` /* 元組相當於關係資料庫中的一條記錄,它將多個任意數據類型的值合併為一個值。 元組類型的值的語法格式為:(元素1, 元素2, ..., 元素n)。 */ let turple = ("張三", 18, true) // let turple: (String, Int, Bool) = (... ...
  • 一般對於android手機,我們可以通過sdk提供的方法判斷網路情況 註意的是對於Tv項目,android系統的Tv(比如小米電視),有的是支持有線連接的(非wifi,2g 3g 4g)的 , 此時上述方法會判斷為0,無網路連接狀態,所以對於Tv項目,需要對網路適配進行相容 解決辦法就是ping一個 ...
  • 問題: 在開發中會遇到動態添加 script 標簽的情況。 代碼如下: 但是在 IE8 以下會報如下錯誤: 查看 MDN 之後發現,在 IE9 以下不支持 解決辦法: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...