1. 程式人生 > 實用技巧 >陣列常用的方法

陣列常用的方法

  • 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