文章目錄
Vuex 是什麼
Vuex是什麼javascript
- 一個專爲
Vue.js
應用程序開發的響應式狀態管理模式.
狀態管理是什麼?
從我我的角度來看,狀態能夠指代數據。而狀態管理也就能夠看做數據管理,主要是用於分層解耦。html
在Vuex
中狀態管理能夠看做是全局變量,這個變量能夠經過state
取出變量映射到view
中,也能夠根據用戶的輸入actions
改變該變量vue
響應式是什麼?
從我我的角度來看,響應式就是自適應。java
在Vuex
中響應式是指數據(狀態)的改變可以及時的全部數據變動爲最新的數據。git
不用 Vuex 也是能夠的
- 從父組件一層一層將數據傳遞給子組件(麻煩)
- 經過 EventBus 的訂閱/發佈模式實現數據數據傳遞
可看這篇文章介紹:什麼狀況下我應該使用 Vuexgithub
使用
安裝
npm 安裝web
npm install vuex --save
知識儲備
全局 store
參考:shoppint-cart 示例
在 store
目錄下建立index.js
vuex
import Vue from 'vue' import Vuex from 'vuex' 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({ // 注入其它模塊的 store modules: { cart, products }, strict: debug, plugins: debug ? [createLogger()] : [] })
在app.js
中注入store
,如:npm
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) })
如在counter
組件中經過this.$store
去使用緩存
this.$store.commit('increment')
State
用於聲明數據。
computed 計算屬性
對於任何複雜邏輯,你都應當使用計算屬性。
例以下面的示例中,第二個 message ,若是咱們要在 view 中寫也是能夠,可是會比較複雜,以下:
<p>Computed reversed message: "{ { message.split('').reverse().join('') }}"</p>
那麼咱們能夠將該複雜寫法經過計算屬性
封裝成一個方法,直接調用該方法對象
便可。
示例:
<div id="example"> <p>Original message: "{ { message }}"</p> <p>Computed reversed message: "{ { reversedMessage }}"</p> <!-- 在 Vuex 中若是不用計算屬性,咱們須要這麼寫 --> <p>Computed reversed message: "{ { this.$store.state.counter.message.split('').reverse().join('') }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 計算屬性的 getter reversedMessage: function () { // `this` 指向 vm 實例 // 使用 vuex 則可經過 $store 取到數據以後再轉換,以下 // return this.$store.state.counter.message.split('').reverse().join('') return this.message.split('').reverse().join('') } } }) 輸出結果: Original message: "Hello" Computed reversed message: "olleH"
mapState 輔助函數
當一個組件須要獲取多個狀態的時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用
mapState
輔助函數幫助咱們生成計算屬性。
輔助函數,用於簡化this.$store.state
,示例以下:
<template> <div> <!-- 直接使用 --> Clicked: { { $store.state.counter.count }} times. <br> <!-- 使用 Vuex mapState --> mapState使用: { { count }} times. </div> </template> <script> // 在單獨構建的版本中輔助函數爲 Vuex.mapState import { mapState } from 'vuex' export default { computed:{ ...mapState({ count: state => state.counter.count }), }, methods: { } } </script>
有時候咱們須要從 store
中的 state
中派生出一些狀態。
如上面的字符串反轉功能就是派生出來的,咱們可使用Getters
去實現。
Getters
能夠認爲是
store
的計算屬性。getter
的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。
經過一個示例來看一下getters
如何使用。
Counter.vue
文件以下:
<template> <div> <p>hello 字符串反轉:{ { reverseStr }}</p> <p>getter 獲取 todo done: { { doneTodosCount }}</p> <p>傳入 getters 作參數:{ { doneTodosCount }}</p> <p>直接訪問:{ { doneTodos }}</p> </div> </template> <script> // 在單獨構建的版本中輔助函數爲 Vuex.mapGetters import { mapGetters } from "vuex"; export default { computed: { // 因爲使用了命名空間,所以須要加上,不然獲取反轉的字符串如: reverseStr:'counter/reverseStr' ...mapGetters('counter',{ reverseStr: "reverseStr", doneTodosCount: "doneTodosCount", doneTodos: "doneTodos", }), }, }; </script>
counter.js
文件以下:
const state = () => ({ message: 'hello', todos: [{ id: 1, text: '寫日報', done: true }, { id: 2, text: '看一篇英文文章', done: false } ] }) // getters const getters = { doneTodos: state => { return state.todos.filter(todo => todo.done) }, doneTodosCount: (state, getters) => { // 傳入 getters 作參數 return getters.doneTodos.length }, reverseStr: state => { return state.message.split('').reverse().join('') } } export default { namespaced: true, state, getters, }
Mutations
經過提交 mutation
的方式,而非直接改變 store.state.count
。
其實也就是經過方法的方式去操做數據。並且Mutation
必須是同步函數,若是是異步函數請使用下一節的Action
看個示例:每次點擊increment
文本+2,每次點擊decrement
文本-2
Counter.vue
文件以下
<template> <div> <p @click="mIncrement">mutations 獲取 increment: { { mutationsCount }}</p> <p @click="mDecrement">mutations 獲取 decrement: { { mutationsCount }}</p> </div> </template> <script> // 在單獨構建的版本中輔助函數爲 Vuex.mapState import { mapState } from "vuex"; export default { computed: { ...mapState({ count: (state) => state.counter.count, mutationsCount: (state) => state.counter.mutationsCount, }), }, methods: { mIncrement() { this.$store.commit("counter/mIncrement",2); }, mDecrement() { this.$store.commit("counter/mDecrement",{ amount:2 }); }, }, }; </script>
counter.js
以下:
const state = () => ({ mutationsCount:0, }) const mutations = { mIncrement(state, n) { state.mutationsCount += n }, // 經過對象傳遞 mDecrement(state,payload) { state.mutationsCount -= payload.amount }, } export default { namespaced: true, state, mutations }
Actions
Action
相似於 mutation
,不一樣在於:
Action
提交的是mutation
,而不是直接變動狀態。Action
能夠包含任意異步操做。
counter
計數器示例:
Counter.vue
文件以下:
<template> <div> Clicked: { { $store.state.counter.count }} times. <br /> <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <script> // 在單獨構建的版本中輔助函數爲 Vuex.mapState import { mapState, mapGetters } from "vuex"; export default { computed: { ...mapState({ count: (state) => state.counter.count, }), }, methods: { increment() { this.$store.dispatch("counter/increment"); }, decrement() { this.$store.dispatch("counter/decrement"); }, }, }; </script>
counter.js
文件以下:
const state = () => ({ count: 0, }) const mutations = { increment(state) { state.count++ }, decrement(state) { state.count-- }, } const actions = { increment: ({ commit }) => commit('increment'), decrement: ({ commit }) => commit('decrement'), } export default { namespaced: true, state, actions, mutations }
Modules
也就是分模塊。
例如Counter
組件,在 store/modules
下建立counter.js
用於處理store
相關的數據,而Counter.vue
組件頁面就正常寫便可。
接着在store/
目錄下的 index.js
添加 module
的注入。具體可看上文的store
全局注入。
購物車示例
對照上面的分析,你能夠很容易看懂Vuex examples 中的 shoppint-cart
示例了
shoppint-cart 示例地址
該示例是經過shop.js
模擬數據,而後將products 和 cart
組件注入全局 store
而後ProductList.vue
展現shop.js
中的商品列表,而ShoppingCart.vue
展現購物車數據。
END~
本文同步分享在 博客「_龍衣」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。