陣列常用的方法
- Vuex 概述
- Vuex 的基本使用
- Vuex 的核心概念
- 基於 Vuex 的案例
1.Vuex 概述
①元件之間共享資料的方式
父向子傳值: v-bind 屬性繫結
子向父傳值: v-on 事件繫結
兄弟元件之間共享資料: EventBus
- $on 接收資料的那個元件
- $emit 傳送資料的那個元件
上面這三種共享資料的方式只適合在小範圍內進行資料的共享,如果我們需要頻繁的、大範圍的實現資料的共享,這三種方案就有點力不從心了
②Vuex 是什麼
Vuex 是實現元件全域性狀態(資料)管理的一種機制,可以方便的實現元件之間資料的共享。
vuex本質就是實現資料共享的:
③使用 Vuex 統一管理狀態的好處
- 能夠在 vuex 中集中管理共享的資料,易於開發和後期維護
- 能夠高效地實現元件之間的資料共享,提高開發效率
- 儲存在 vuex 中的資料都是響應式的,能夠實時保持資料與頁面的同步
④什麼樣的資料適合儲存到 Vuex 中
一般情況下,只有元件之間共享的資料,才有必要儲存到 vuex 中;對於元件中的私有資料,依舊儲存在元件自身的 data 中即可。
2.Vuex 的基本使用
①安裝 vuex 依賴包
npm install vuex --save
②匯入 vuex 包
import Vuex from 'vuex'
Vue.use(Vuex)
③建立 store 物件
const store = new Vuex.Store({ // state 中存放的就是全域性共享的資料 state: { count: 0 } })
④將 store 物件掛載到 vue 例項中
new Vue({ el: '#app', render: h => h(app), router, // 將建立的共享資料物件,掛載到 Vue 例項中 // 所有的元件,就可以直接從 store 中獲取全域性的資料了 store })
3.Vuex 的核心概念
Vuex 中的主要核心概念如下:
- State
- Mutation
- Action
- Getter
①State
State 提供唯一的公共資料來源,所有共享的資料都要統一放到 Store 的 State 中進行儲存。
// 建立store資料來源,提供唯一公共資料 const store = new Vuex.Store({ state: { count: 0 } })
元件訪問 State 中資料的第一種方式:
this.$store.state.全域性資料名稱
在template區域,this是可以省略的:
元件訪問 State 中資料的第二種方式:
// 1. 從 vuex 中按需匯入 mapState 函式 import { mapState } from 'vuex'
通過剛才匯入的 mapState 函式,將當前元件需要的全域性資料,對映為當前元件的 computed 計算屬性:
// 2. 將全域性資料,對映為當前元件的計算屬性 computed: { ...mapState(['count']) }
實現+1的效果:
雖然能夠實現所需的功能,但是這種做法是完全不對的。因為我們在當前元件中直接修改了$store全域性資料,但是在vuex中不允許元件直接修改store裡面的資料,所以上面的程式碼是完全不合法的。
那在vuex中是推薦哪種方式來修改store裡面的公有資料呢?
如果我們使用在元件中直接修改store資料的方式,隨著我們的專案越寫越大,如果我們想看一下到底是哪個元件修改了store裡面的資料,我們得挨個去元件裡面找,不利於後期的維護。但是如果我們使用mutations來集中式修改state中的資料,可以方便後期的維護。
②Mutation
Mutation 用於變更 Store中 的資料。
只能通過 mutation 變更 Store 資料,不可以直接操作 Store 中的資料。
通過這種方式雖然操作起來稍微繁瑣一些,但是可以集中監控所有資料的變化。
// 定義 Mutation const store = new Vuex.Store({ state: { count: 0 }, mutations: { add(state) { // 變更狀態 state.count++ } } })
// 觸發mutation methods: { handle1() { // 觸發 mutations 的第一種方式 this.$store.commit('add') } }
可以在觸發 mutations 時傳遞引數:
// 定義Mutation const store = new Vuex.Store({ state: { count: 0 }, mutations: { addN(state, step) { // 變更狀態 state.count += step } } })
// 觸發mutation methods: { handle2() { // 在呼叫 commit 函式, // 觸發 mutations 時攜帶引數 this.$store.commit('addN', 3) } }
commit的作用就是呼叫某個mutation函式
this.$store.commit() 是觸發 mutations 的第一種方式,觸發 mutations 的第二種方式:
// 1. 從 vuex 中按需匯入 mapMutations 函式 import { mapMutations } from 'vuex'
通過剛才匯入的 mapMutations 函式,將需要的 mutations 函式,對映為當前元件的 methods 方法:
// 2. 將指定的 mutations 函式,對映為當前元件的 methods 函式 methods: { ...mapMutations(['add', 'addN']) }
實現一個功能:點選按鈕後延遲一秒再顯示count的值
按我們正常的思維會在mutation對應的方法中新增一個定時器,但是出現一個問題:
頁面顯示的效果中是沒有什麼問題的,但是可以看到vue偵錯程式中的count狀態值卻並沒有發生變化。
這是因為在mutations函式中,不能寫非同步的程式碼,而定時器就是非同步的方法!
那如何執行非同步操作呢?
③Action
Action 用於處理非同步任務。
如果通過非同步操作變更資料,必須通過 Action,而不能使用 Mutation,但是在 Action 中還是要通過觸發Mutation 的方式間接變更資料。
// 定義 Action const store = new Vuex.Store({ // ...省略其他程式碼 mutations: { add(state) { state.count++ } }, actions: { addAsync(context) { setTimeout(() => { context.commit('add') }, 1000) } } })
// 觸發 Action methods: { handle() { // 觸發 actions 的第一種方式 this.$store.dispatch('addAsync') } }
dispatch函式專門用來觸發action。
只有mutation中定義的函式,才有權利修改state中的資料
觸發 actions 非同步任務時攜帶引數:
// 定義 Action const store = new Vuex.Store({ // ...省略其他程式碼 mutations: { addN(state, step) { state.count += step } }, actions: { addNAsync(context, step) { setTimeout(() => { context.commit('addN', step) }, 1000) } } })
// 觸發 Action methods: { handle() { // 在呼叫 dispatch 函式, // 觸發 actions 時攜帶引數 this.$store.dispatch('addNAsync', 5) } }
this.$store.dispatch() 是觸發 actions 的第一種方式,觸發 actions 的第二種方式:
// 1. 從 vuex 中按需匯入 mapActions 函式 import { mapActions } from 'vuex'
通過剛才匯入的 mapActions 函式,將需要的 actions 函式,對映為當前元件的 methods 方法:
// 2. 將指定的 actions 函式,對映為當前元件的 methods 函式 methods: { ...mapActions(['addASync', 'addNASync']) }
④Getter
Getter 用於對 Store 中的資料進行加工處理形成新的資料。
注意:Getter不會修改store裡面的源資料,它只是起到包裝資料的作用
- Getter 可以對 Store 中已有的資料加工處理之後形成新的資料,類似 Vue 的計算屬性。
- Store 中資料發生變化, Getter 的資料也會跟著變化。
// 定義 Getter const store = new Vuex.Store({ state: { count: 0 }, getters: { showNum: state => { return '當前最新的數量是【'+ state.count +'】 ' } } })
使用 getters 的第一種方式:
this.$store.getters.名稱
使用 getters 的第二種方式:
import { mapGetters } from 'vuex' computed: { ...mapGetters(['showNum']) }
4.基於 Vuex 的案例
使用vuex做一個TodoList的小案例:
①初始化專案
- 通過 vue ui 命令開啟視覺化面板,建立新專案 vuex-demo2
- 安裝 vuex 依賴包 npm install vuex axios ant-design-vue –S
- 實現 Todos 基本佈局(基於已有樣式模板)
②完成具體功能
- 動態載入任務列表資料
- 實現文字框與store資料的雙向同步
- 完成新增任務事項的操作
- 完成刪除任務事項的操作
- 動態繫結複選框的選中狀態
- 修改任務事項的完成狀態
- 統計未完成的任務的條數
- 清除已完成的任務事項
- 實現任務列表資料的動態切換
建立一個新專案:
開啟Babel,vuex,linter/fomatter,use config files:
需要安裝的依賴:axios、ant-design-vue。
1)實現資料動態渲染到頁面上
通過axios請求list.json檔案裡面的資料,如何發請求來獲取資料呢?
在store.js中匯入axios,注意,axios請求是非同步操作,所以必須在action中傳送請求
在App.vue元件中呼叫該函式:
如何將資料渲染到頁面上呢?需要將請求獲取到的資料掛載到state裡面來進行儲存
2)實現文字框中的內容的雙向同步
首先在store檔案中的state中定義一個全域性資料inputValue,需要將App.vue元件中的文字框的value屬性動態繫結到該資料上 只需要將該屬性對映到計算屬性中去,併為文字框監聽一個change事件,拿到文字框最新的值,然後再同步到state中去3)點選新增事項的功能
為新增事項按鈕新增一個點選事件
this.$message.warning是由ant-design的UI元件庫提供的
4)實現刪除事件的功能
為每一個刪除按鈕新增一個點選事件,在呼叫該事件函式同時並把這條資料的id傳遞過去
5)實現複選框狀態的繫結
6)修改任務完成狀態的功能
點選任務事項對應的複選框,能夠拿到該複選框最新的狀態,然後再根據這一項的id複製到對應的list陣列中
監聽複選框狀態改變的change事件
7)統計未完成的任務條數
需要用到vuex中的getters
8)清除已完成任務的功能
為該按鈕新增一個點選事件
9)實現列表底部三個按鈕(全部、未完成、已完成)的高亮狀態的切換
點選不同的按鈕能夠切換不同按鈕的高亮效果10)實現列表資料的按需切換
基於vuex實現TodoList功能的程式碼地址:vuex_todolist