Vuex 學習筆記

Vuex 是什么?

Vuex 是一個專為 Vue.js應用程序開發的狀態管理模式。由于SPA應用的模塊化,每個組件都有它各自的數據(state)、視圖(view)和方法(actions),當項目內容越來越多時,每個組件中的狀態就變得很難管理。Vuex 就是采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。

?

1、單個組件中的狀態

看一下官網提供的計數示例:

<template><div><button class="btn btn-success" @click="increment">increment</button>
      view: {{count}}</div>
</template><script>export default {// state
        data () {return {count: 0}},// actions
        methods: {increment () {this.count++}}}
</script>

運行結果:

從效果圖中可以直觀的看到,每點擊一次按鈕觸發添加事件(actions),數據count(state)就會發生改變,然后映射到視圖界面(view)中。

下圖可以表示 “ 單項數據流 ” 理念的極簡示意:

這個狀態管理應用包含以下幾個部分:

? state:驅動應用的數據源

? view:以聲明方式將 state 映射到視圖

? actions:響應在 view 上的用戶輸入導致的狀態變化

?

2、多個組件中的狀態

當我們的應用遇到 多個組件共享狀態 時,單向數據流的簡潔性很容易被破壞:

? 多個視圖依賴于同一狀態

? 來自不同視圖的行為需要變更同一狀態

?

同樣是計數器,我們現在更換一種場景,兩個相同的組件A和B,共享一個數據count,并且都有一個方法可以操作這個count(是不是跟上面提到的多組件共享狀態描述的一樣呢)

// 組件A
<template><div>{{ $store.state.count }}<button @click="increment">組件A</button></div>
</template><script>export default {methods: {increment () {this.$store.commit('increment')}}}
</script>//組件B
<template><div>{{ $store.state.count }}<button @click="increment">組件B</button></div>
</template><script>export default {methods: {increment () {this.$store.commit('increment')}}}
</script>

運行效果:

從圖中可以看到,“組件A” 和 “組件B” 兩個按鈕 會同時改變兩個 count 的數據,因為數據源 count 和 方法increment 都是全局的。如下圖所示,我們把 全局數據源 state改變數據源的方法 mutations異步操作方法 actions 提取出來放到 store 中,實現全局數據狀態單獨管理的功能

安裝?

1、使用 npm 安裝并保存到 package.json 中

npm install vuex --save

package.json

"dependencies": {...,...,...,"vuex": "^2.4.1"},

?

2、配置

// 如果在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex)
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)//創建Store實例
const store = new Vuex.Store({// 存儲狀態值
  state: {...},// 狀態值的改變方法,操作狀態值// 提交mutations是更改Vuex狀態的唯一方法
  mutations: {...},// 在store中定義getters(可以認為是store的計算屬性)。Getters接收state作為其第一個函數
  getters: {...},actions: { ...}
})
// 要改變狀態值只能通過提交mutations來完成/* eslint-disable no-new */
const app = new Vue({router,i18n,// 將 store 實例注入到根組件下的所有子組件中,子組件通過 this.$store 來訪問store
    store,...App
})app.$mount('#app')

看一下官網提供的例子:

<template><div><p>{{ count }}</p><p><button @click="increment">+</button><button @click="decrement">-</button></p></div>
</template><script>export default {computed: {count () {// 通過 store.state 來獲取狀態對象return this.$store.state.count}},methods: {increment () {// 通過 store.commit 方法觸發狀態變更this.$store.commit('increment')},decrement () {this.$store.commit('decrement')}}}
</script>
// 創建 Store 實例
const store = new Vuex.Store({// 存儲狀態值
    state: {count: 0},// 狀態值的改變方法,操作狀態值// 提交 mutations 是更改Vuex狀態的唯一方法
    mutations: {increment: state => state.count++,decrement: state => state.count--}
})

運行效果:

?

核心概念

1、State

state 就是全局的狀態(數據源),從前面的例子中看到我們可以按如下方式獲取 Vuex 的state 狀態

// html 中
{{ $store.state.count }}// js 中
this.$store.state.count

?

2、Getter

getter 可以認為是 store 的計算屬性,跟計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會重新計算

如下官網提供的案例:

computed: {doneTodosCount () {return this.$store.state.todos.filter(todo => todo.done).length}
}

如果有多個組件需要用到此屬性,我們要么復制這個函數,或者抽取到一個共享函數然后在多處導入它,然而這兩種方法都不是很理想,最佳方式當然是使用 getter 了

我們嘗試使用下getter

(1)、定義 getter

const store = new Vuex.Store({state: {count: 0},getters: {formatMoney: state => {return '¥'+state.count.toFixed(2)+'元'}},mutations: {increment: state => state.count++}
})

(2)、在組件中引用 getter

export default {methods: {increment () {this.$store.commit('increment')// 這里為了更清楚的看到計算后的值let aaa = document.getElementById('aaa')let p = document.createElement('p')p.innerHTML = this.$store.getters.formatMoneyaaa.appendChild(p)}},computed: {formatMoney() {return this.$store.getters.formatMoney}}}

效果:

3、Mutation

更改 Vuex 的 store 中的狀態的唯一方法就是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型(type)和一個 回調函數(handler),這個回調函數就是我們實際進行狀態更改的地方,并且它會接受 state 作為第一個參數:

const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) {// 變更狀態state.count++}}
})

要喚醒一個 mutation handler,你需要以相應的 type 調用 store.commit 方法

store.commit('increment')

?

(1)、提交載荷(Payload)

載荷(payload)就是說 可以向 store.commit 傳入額外的參數

// ...
mutations: {increment (state, n) {state.count += n}
}
store.commit('increment', 10)

在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段并且記錄的mutation會更易讀:

// ...
mutations: {increment (state, payload) {state.count += payload.amount}
}
store.commit('increment', {amount: 10
})

?

4、Action

Vuex 中一條重要的原則就是 mutation 必須是同步函數, action 類似于 mutation,不同之處在于:

? Action 提交的是 mutation,而不是直接變更狀態

? Action 可以包含任意異步操作

const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}},actions: {increment (context) {context.commit('increment')},// 異步
    incrementAsync (context) {// 延時1秒setTimeout(() => {context.commit('increment')}, 1000)}} 
})

Action 函數接受一個與 store 實例具有相同方法和屬性的context對象,因此,可以有以下調用方法

? context.commit ?提交一個 mutation

? context.state ?獲取 state

? context.getters ? 獲取 getters

不同于 mutation 使用 commit 方法,action 使用 dispatch 方法

store.dispatch('increment')

Actions 同樣支持 載荷方式 和 對象方式 進行分發:

// 以載荷形式分發
store.dispatch('incrementAsync', {amount: 10
})// 以對象形式分發
store.dispatch({type: 'incrementAsync',amount: 10
})

?

5、Module

由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象,當應用變得非常復雜時,store 對象就有可能變得非常臃腫。

為了解決以上問題,Vuex 允許我們將 store 分割成 模塊(module),每個模塊擁有自己的 state、mutation、getter、action,甚至是嵌套子模塊 --- 從上至下進行同樣方式的分割

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 的狀態

?

關于項目結構,我們可以看看官網提供的示例:

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API請求
├── components
│   ├── App.vue
│   └── ...
└── store├── index.js          # 我們組裝模塊并導出 store 的地方├── actions.js        # 根級別的 action├── mutations.js      # 根級別的 mutation└── modules├── cart.js       # 購物車模塊└── products.js   # 產品模塊

官網同時也提供了一個 購物車 示例:

app.js 文件如下:

import 'babel-polyfill'
import Vue from 'vue'
import App from './components/App.vue'
import store from './store'
import { currency } from './currency'Vue.filter('currency', currency)new Vue({el: '#app',store,render: h => h(App)
})

index.js 文件如下:

import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import cart from './modules/cart'
import products from './modules/products'
import createLogger from '../../../src/plugins/logger'Vue.use(Vuex)const debug = process.env.NODE_ENV !== 'production'export default new Vuex.Store({actions,getters,modules: {cart,products},strict: debug,plugins: debug ? [createLogger()] : []
})

getters.js 文件如下:

export const cartProducts = state => {return state.cart.added.map(({ id, quantity }) => {const product = state.products.all.find(p => p.id === id)return {title: product.title,price: product.price,quantity}})
}

actions.js 文件如下:

import * as types from './mutation-types'export const addToCart = ({ commit }, product) => {if (product.inventory > 0) {commit(types.ADD_TO_CART, {id: product.id})}
}

mutation-type.js 文件如下:

export const ADD_TO_CART = 'ADD_TO_CART'
export const CHECKOUT_REQUEST = 'CHECKOUT_REQUEST'
export const CHECKOUT_SUCCESS = 'CHECKOUT_SUCCESS'
export const CHECKOUT_FAILURE = 'CHECKOUT_FAILURE'
export const RECEIVE_PRODUCTS = 'RECEIVE_PRODUCTS'

cart.js 文件如下:

import shop from '../../api/shop'
import * as types from '../mutation-types'// initial state
// shape: [{ id, quantity }]
const state = {added: [],checkoutStatus: null
}// getters
const getters = {checkoutStatus: state => state.checkoutStatus
}// actions
const actions = {checkout ({ commit, state }, products) {const savedCartItems = [...state.added]commit(types.CHECKOUT_REQUEST)shop.buyProducts(products,() => commit(types.CHECKOUT_SUCCESS),() => commit(types.CHECKOUT_FAILURE, { savedCartItems }))}
}// mutations
const mutations = {[types.ADD_TO_CART] (state, { id }) {state.lastCheckout = nullconst record = state.added.find(p => p.id === id)if (!record) {state.added.push({id,quantity: 1})} else {record.quantity++}},[types.CHECKOUT_REQUEST] (state) {// clear cartstate.added = []state.checkoutStatus = null},[types.CHECKOUT_SUCCESS] (state) {state.checkoutStatus = 'successful'},[types.CHECKOUT_FAILURE] (state, { savedCartItems }) {// rollback to the cart saved before sending the requeststate.added = savedCartItemsstate.checkoutStatus = 'failed'}
}export default {state,getters,actions,mutations
}

products.js 文件如下:

import shop from '../../api/shop'
import * as types from '../mutation-types'// initial state
const state = {all: []
}// getters
const getters = {allProducts: state => state.all
}// actions
const actions = {getAllProducts ({ commit }) {shop.getProducts(products => {commit(types.RECEIVE_PRODUCTS, { products })})}
}// mutations
const mutations = {[types.RECEIVE_PRODUCTS] (state, { products }) {state.all = products},[types.ADD_TO_CART] (state, { id }) {state.all.find(p => p.id === id).inventory--}
}export default {state,getters,actions,mutations
}

購物車運行效果:

轉載于:https://www.cnblogs.com/rogerwu/p/7606156.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280241.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280241.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280241.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

xdf文檔怎么轉換為pdf_如何將PDF文件和圖像轉換為Google文檔文檔

xdf文檔怎么轉換為pdfYou probably know you can create and edit documents with Google Docs, but you can edit more than just .doc files. Google Drive can also convert any PDF, JPG, PNG, or GIF into a document with fully editable text. Here’s how. 您可能知道可…

在現代 Windows 上使用經典 Windows 2000、XP、Vista 任務欄

你好&#xff0c;這里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;實用的工具和組件&#xff0c;希望對您有用&#xff01;前言您第一次使用的 Windows 是哪個版本的&#xff1f;我最早使用的 Windows XP&#xff0c;然后再經過 XP、7、8/8.1 、Windows 10&a…

oracle sys可以登錄,system權限不足,解決方法

今天在自己電腦上安裝了oracle 11g&#xff0c;安裝成功后發現 sys 可以正常登錄。system 無法登錄&#xff0c;顯示 ORA-01031: insufficient privileges(權限不足) select * from v$pwfile_users; 查看有sysdba權限的用戶 grant sysdba to system; 給system 授權sysdba權限…

airdroid黑屏_如何使用AirDroid從PC控制Android設備

airdroid黑屏AirDroid for Android replaces your USB cable for connecting to your PC. Transfer files back and forth, send text messages, play music, view your photos, and manage applications using a web browser or a desktop client. 適用于Android的AirDroid取代…

分析java程序

2019獨角獸企業重金招聘Python工程師標準>>> 最近公司的一個賬單推送的服務&#xff0c;發現有延遲。我排查的時候發現&#xff0c;有一個程序日志不動了&#xff08;采用消息隊列&#xff0c;部署了兩臺服務器來負載均衡&#xff09;。 網上說&#xff1a; jstack …

環境部署(九):linux下安裝python+chrome+Xvfb

在基于selenium進行的UI自動化測試中&#xff0c;開發調試環境一般都是windows操作系統。完成后需要部署到專門的測試環境。 如要要部署到linux環境的服務器&#xff08;阿里云、騰訊云&#xff09;執行&#xff0c;那么測試腳本也需要對應的瀏覽器支持&#xff0c; 才能正常進…

地理圍欄_什么是“地理圍欄”?

地理圍欄The term is popping up more frequently in news articles, appearing in product manuals, and highlighted as a feature in tons of mobile applications, but what exactly is geofencing? Read on as we explain what it is, why it’s appearing in more produ…

219. 單頁應用 會話管理(session、cookie、jwt)

原文鏈接&#xff1a;https://github.com/ly525/blog... 關鍵字&#xff1a;http-only, cookie,sessionid, vue-router, react-router, 安全&#xff0c;localStorage, jwt 需求描述 內部管理平臺&#xff0c;需要用戶登錄之后才能訪問。現在將 該平臺地址&#xff08;www.xxx.…

(原+譯)使用numpy.savez保存字典后讀取的問題

轉載請注明出處&#xff1a; http://www.cnblogs.com/darkknightzh/p/7608928.html 參考網址; https://stackoverflow.com/questions/22315595/saving-dictionary-of-header-information-using-numpy-savez python中&#xff0c;使用pickle保存變量時&#xff0c;如果變量過大&…

NLog 通過http保存日志

簡介NLog是一個基于.NET平臺編寫的類庫&#xff0c;我們可以使用NLog在應用程序中添加極為完善的跟蹤調試代碼。 NLog是一個簡單靈活的.NET日志記錄類庫。通過使用NLog&#xff0c;我們可以在任何一種.NET語言中輸出帶有上下文的&#xff08;contextual information&#xff09…

嵌套映射

1. 多對一嵌套查詢映射使用案例 package com.zixue.dao;import com.zixue.annotation.MyBatisRepository; import com.zixue.entity.Emp;/*** 員工表的DAO組件* */ MyBatisRepository public interface EmpDao {void save(Emp emp);Emp findById(int id);Emp findById2(int id)…

gopro dataset_如何將GoPro安裝到DSLR相機

gopro datasetIf you have a DSLR camera with a hot shoe, it’s easy to attach various flashes and other accessories right to your camera. But with a couple of cheap attachments on hand, you can mount your GoPro to your DSLR camera as well. 如果您的DSLR相機帶…

音頻 m4a 轉 wav

背景最近做智能家居&#xff0c;需要用到一些應答詞 需要自己錄制。但是在mac下面通過 QuickTime 錄制的是 m4a格式。但是應答詞需要 wav格式。所以就需要轉化了解決方法# sox 不行&#xff0c; ffmpeg 很麻煩&#xff0c;用 avconv 很簡單。安裝 如果沒有就安裝 # apt-get ins…

jQuery已經過時了,還需要學嗎?

說起jQuery&#xff0c;很多剛參加工作的程序員都沒用過&#xff0c;甚至沒聽過。曾幾何時jQuery可是秒殺一切Js庫&#xff0c;大有一統江山的情況&#xff0c;可是在頂峰的時候&#xff0c;瞬間被Vue、React、Angela三大框架斬于馬下。從百度指數&#xff0c;我們也看出在2015…

Bootstrap01

Bootstrap01內容概要 一.使用Bootstrap的步驟 1.下載Bootstrap類庫,包含三個部分,fonts,css,Bootstrap 2.導入項目中,在頭部引入JQ,css和Bootstrap 注意:JQ要引入在Bootstrap前面! 3.使用css樣式時,全部使用class屬性 二.全局CSS概要 1.僅支持H5文檔格式 2.移動設備優先,需要在…

ios raise_如何在iOS 10中關閉“ Raise to Wake”

ios raiseRaise to Wake is a new Lock screen feature available in iOS 10. It allows you to wake your phone’s screen simply by picking up your phone. This feature is on by default, but if you’d rather not use it, it’s simple to turn off. “喚醒”是iOS 10中…

資源調度器調研

2019獨角獸企業重金招聘Python工程師標準>>> 場景描述&#xff1a; 異步觸發和Crontab觸發 YARN(Yet Another Resource Negotiator)Hadoop 資源管理器 主要構成&#xff1a; RM(ResourceManager)是一個全局的資源管理器&#xff0c;負責整個系統的資源管理和分配。…

WPF-19 IValueConverter接口

我們先來看看微軟官方給出的定語&#xff1a;提供將自定義邏輯應用于綁定的方法&#xff0c;我們來看一下該接口的定義&#xff0c;Convert提供了將數據源到UI的格式化&#xff0c;ConvertBack表示反向namespace System.Windows.Data {//// Summary:// Provides a way to a…

JVM學習記錄-類加載的過程

類的整個生命周期的7個階段是&#xff1a;加載&#xff08;Loading&#xff09;、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸載(Unloading)。 類加載的全過程主要包括&#xff1a;加載、驗證、準備、解析、初始化這5個…

使用 Azure CLI 將 IaaS 資源從經典部署模型遷移到 Azure Resource Manager 部署模型

以下步驟演示如何使用 Azure 命令行接口 (CLI) 命令將基礎結構即服務 (IaaS) 資源從經典部署模型遷移到 Azure Resource Manager 部署模型。 本文中的操作需要 Azure CLI。 Note 此處描述的所有操作都是冪等的。 如果你遇到功能不受支持或配置錯誤以外的問題&#xff0c;建議你…