1. 程式人生 > 實用技巧 >Vuex與元件通訊

Vuex與元件通訊

概述

vuex 是一個專為vue.js應用程式開發的狀態管理模式。也就是說 Vuex 用於單頁面應用元件之間的資料共享,在元件巢狀很多層的情況下,Vue 中父子元件的通訊過程就變得很麻煩,此時使用 Vuex 方便了元件間的通訊。vuex官網上說是一個vue的狀態管理工具。其實我們可以簡單地把狀態理解成為vue的data裡面的變數。當元件之間的data變數關係複雜一點的時候,就把其中的變數抽離出來管理。Vuex提供了一個數據倉庫,存放著各種資料data。誰要用誰去請求num的值,誰想改就改該多好是吧,vuex就是幹這個的,有點全域性變數的意思。任何元件需要拿,改東西,都可以找他。

Vuex主要涉及到state,getters,mutations,actions。

state:是驅動應用的資料來源,是惟一的資料載體,跟倉庫一樣。
mutations:更改state的唯一方法,意思是修改、增加等處理state的方法,
getters:從state中派生出的一些狀態,如獲取資料的陣列的長度,方便其他元件獲取使用。簡單來說,就是過濾,計算,組合!
actions:用來提交mutations,通過commit再去觸發對應的mutations,而不是直接變更state狀態。

稍微簡單點的vuex管理就使用 state和 mutations這兩個就行。複雜的vuex管理還會涉及到modules等輔助方法。

應用例項:Todo-list

本文旨在通過一個簡單的todo list例子,熟悉vuex常見的方法,瞭解元件間資料共享機制。

本文示例中,分為父元件Main.vue,兩個子元件List.vue和Add.vue,父元件包含兩個子元件,實時顯示列表長度,子元件Add.vue負責新增列表項,List.vue負責顯示列表,以及刪除列表項。在子元件新增和刪除列表項時,相應的元件會聯動:父元件會實時計算列表長度,List元件會增減列表項。大家可以先觀看效果:Demo。

1. 準備

本例項採用 Vue2 + Vue Router + Vuex + vue-ydui 實現。 我們事先已經建立了Vuewebpack模板,並安裝相關元件。

npm install --save vuex
npm install --save vue-router
npm install --save vue-ydui

2. 建立資料倉庫

在src目錄下建立資料夾store/,並在store/目錄下新建index.js檔案。

import Vue from 'vue'
import Vuex from "vuex"
Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        message: '',
        todoList: [{id: 0, value: 'default'}]
    },
    getters: {
        //計算list長度
        listCount(state) {
            return state.todoList.length;
        }
    },
    mutations: {
        //新增
        addTodo(state, item) {
            state.todoList.push(item);
        },
        //刪除
        delTodo(state, index) {
            state.todoList.splice(index, 1);
        },
        //設定錯誤提示資訊
        showError(state, msg) {
            state.message = msg;
        }
    },
    actions: {
        //提交addTodo
        addTodo(context, item) {
            if (item.value == '') {
                context.commit('showError', '請輸入內容');
            } else {
                context.commit('addTodo', item);
                context.commit('showError', '');
            }
        },
        //提交delTodo
        delTodo({commit}, index) {
            commit('delTodo', index);
        }
    },
    modules: {}
});

export default store;

如上程式碼和註釋,我們在store/index.js中設定了資料以及修改這些資料的方法。

3. main.js

在main.js中將store.js加進來。示例中我們還用到了UI庫:vue-ydui,也一起加進來。

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

import YDUI from 'vue-ydui';
import 'vue-ydui/dist/ydui.rem.css';

Vue.use(YDUI);

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '
<app />'
})

4. 設定路由

在router/index.js加入路由設定,讓頁面直接訪問父元件Main.vue。

import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/components/Main'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Main',
      component: Main
    }
  ]
})

5. Main.vue

現在我們來看父元件:

<template>
  <yd-layout>
    <p>這是一個Todo-List示例</p>
    <hw-add></hw-add>
    <hw-list></hw-list>
    <p>todoList 總數:{{listCount}}</p>
    <p>{{msg}}</p>
  </yd-layout>
</template>

<script>
import hwAdd from "./Add.vue";
import hwList from "./List.vue";

export default {
  components: {
    hwAdd,
    hwList
  },
  data(){
    return {
      
    }
  },
  computed: {
    listCount() {
      return this.$store.getters.listCount;
    },
    msg() {
      let message = this.$store.state.message;
      if (message !== '') {
        this.$dialog.toast({
            mes: message,
            timeout: 1500
        });
      }
    }
  }
}
</script>

Main.vue用來展示列表和新增列表項等子元件,已經顯示列表長度和錯誤資訊提示。我們看到在 computed中獲取到資料倉庫中的資料,並顯示在頁面上。

6. Add.vue

Add.vue用來新增列表項。

<template>
    <yd-layout>
        <yd-cell-group>
            <yd-cell-item>
                <yd-icon slot="icon" name="discount" size=".35rem"></yd-icon>
                <input type="text" slot="right" placeholder="請輸入內容" v-model="value" @keyup.enter="addItem">
                <yd-button slot="right" type="warning" @click.native="addItem">新增</yd-button>
            </yd-cell-item>
        </yd-cell-group>

    </yd-layout>
</template>

<script>
export default {
    data() {
        return {
            value: '',
            id: 0
        }
    },
    methods: {
        addItem() {
            let item = {
                value: this.value,
                id: ++this.id
            }
            this.value = '';
            this.$store.dispatch('addTodo', item);
        }
    }
}
</script>

在新增列表項的addItem方法中,我們使用 this.$store.dispatch('addTodo', item);告訴vuex的 addTodo,我們要往todo list中新增新的列表項。

資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com

7. List.vue

List.vue用來展示列表項,並且提供刪除列表項功能。

<template>
    <yd-layout>
        <yd-cell-group title="Todo列表">
            <yd-cell-item v-for="(item,index) in todoList" :key="index" class="list">
                <span slot="left">{{index+1}}.{{item.value}}</span>
                <span slot="right">
                    <yd-icon slot="icon" name="delete" size=".36rem" @click.native="del(index)"></yd-icon>
                </span>
            </yd-cell-item>
        </yd-cell-group>
    </yd-layout>
</template>

<script>
import {mapState} from 'vuex';

export default {
    data() {
        return {
            
        }
    },
    computed: {
        ...mapState([
            'todoList'
        ])
    },
    methods: {
        del(index) {
            this.$store.dispatch('delTodo', index);
        }
    }
}
</script>

上述程式碼中的

computed: {
        ...mapState([
            'todoList'
        ])
    },

其實相當於:

computed: {
        todoList() {
             return this.$store.state.todoList;
        }
},

小結

通過示例我們可以知道,使用Vuex來管理資料共享,各元件無需關注元件間的資料通訊傳輸,一切資料的讀取和更新都是各元件與Vuex資料倉庫間的操作,避免了複雜專案中資料管理混亂的情況發生。

Vuex的使用還有很多優化的寫法,比如 mapState、mapGetters、mapActions,本站後面會有文章講解。當然,如果是小型的專案,我們直接用$emit, props等就能解決元件間的資料通訊問題,不必使用vuex這個傷腦筋的工具。