vue組件間通信的一些實用方法(VUE2.x)

vue組件間通信的一些實用方法(VUE2.x)

一、父子組件間通信

  1. 常用的父子組件通信方法,一般涉及props和$emit之間的交互,也就是我們在vue常說的屬性傳遞和事件映射,實例如下:
<template>
    <div class="parent">
        <child :message="message" @getReply="getReply"></child>
    </div>
</template>

<script>
    import child from './child'

    export default {
        name: 'parent',
        components:{
            child
        },
        data() {
            return {
                message: '你好'
            }
        },
        methods:{
            getReply(message){
                console.log('子組件回復(fù)消息',message);
            }
        }
    }
</script>

<template>
    <div class="child">

    </div>
</template>

<script>
    export default {
        name: 'child',
        props:['message'],
        mounted(){
            //如果接收到父組件傳遞的消息,進行消息回復(fù)
            if(this.props.message){
                this.$emit('getReply','已收到消息');
            }
        }
    }
</script>

說明:上訴代碼中,父組件和子組件在同一文件夾之下,父組件引用并使用了child子組件,并利用message傳遞給子組件一句“你好”。子組件在mounted生命周期獲取屬性message,如果獲取到消息,利用"getReply"事件映射,告訴父組件已收到消息,父組件通過綁定事件的getReply方法進行接收。這就是一個常用的vue父子間通過屬性和事件進行通信的過程。

  1. 子組件調(diào)用父組件的方法,父組件調(diào)用子組件的方法

    • 子組件調(diào)用父組件方法,常用的應(yīng)用場景例如,父組件為一個表格組件,子組件是表單修改或保存的模態(tài)框組件,子組件填寫表單完成后點擊保存,請求成功后需要刷新表格組件。代碼示例如下:

      <!--父組件(表格組件)-->
      <template>
          <div class="table">
              <dialog></dialog>
          </div>
      </template>
      
      <script>
          import dialog from './dialog'
      
          export default {
              name: 'table',
              components:{
                  dialog
              },
               provide() {
                 return {
                     refreshTableData: this.getData,
                 }
             },
              methods:{
                  getData(){
                      //表格獲取請求數(shù)據(jù)的方法,由于只是簡單的示例,所以就不寫實際業(yè)務(wù)代碼了
                  }
              }
          }
      </script>
      
      <!--子組件(表單模態(tài)框)-->
      <template>
          <div class="dialog">
              <!--子組件-->
              <button @click="save">保存</button>
          </div>
      </template>
      
      <script>
          export default {
              name: 'dialog',
              inject: ['refreshTableData'],
              methods:{
                  save(){
                      /*當(dāng)針對表格進行新增或修改操作后,打開模態(tài)框針對表單填寫完畢后進行保存
                     * 這時候通過異步請求數(shù)據(jù)保存成功后,需要父組件的表格數(shù)據(jù)刷新
                     * 就可通過父組件提供的refreshTableData方法進行操作
                     * */
                      this.refreshTableData();
                  }     
              }
          }
      </script>
      

      說明:通過provider和inject提供了子組件調(diào)用父組件的函數(shù)方法,不僅限于函數(shù)方法,也可通過此方法調(diào)用父組件的變量。

  • 父組件調(diào)用子組件的方法和變量的方法相對簡單,可通過ref獲取子組件的實例進行調(diào)用,不過一般不建議這樣使用,相對不太規(guī)范,但是也是一個可行性方案。代碼如下:

    <template>
        <div class="parent">
            <child ref="child"></child>
        </div>
    </template>
    
    <script>
        import child from './child'
    
        export default {
            name: 'parent',
            components:{
                child
            },
            methods:{
                useChildMethod(){
                    this.$refs.child.init();
                }
            }
        }
    </script>
    

    說明:假設(shè)子組件內(nèi)部有一個init的初始化方法,可在父組件通過ref獲取組件實例進行調(diào)用。

二、全局組件間的通信

  1. 利于vuex建立全局的數(shù)據(jù)共享

    全局通信一般的業(yè)務(wù)場景可能是功能菜單、面包屑、頁面之間的聯(lián)動操作,或者購物APP的購物車效果。我們簡單舉例購物車效果的實際應(yīng)用。代碼如下:

    // shoppingBag.js文件
    const shoppingBag = {
      state: {
        goods:[]
      },
    
      mutations: {
        // 設(shè)置一級菜單
        SET_GOODS: (state, goods) => {
          state.goods = goods
        },
      },
    
      actions: {
        setGoods({commit}, goods) {
          commit('SET_GOODS',goods)
        },
      }
    };
    
    export default shoppingBag
    

    上面簡單的作為一個購物車的store模塊,里面定義了goods變量存放商品,提供了一個setGoods方法用于保存商品數(shù)據(jù)。由于只是舉例演示,并沒有書寫真實的業(yè)務(wù)復(fù)雜代碼。真實場景可能是設(shè)計商品名稱、id、數(shù)量等信息,涉及購物車入庫時的相關(guān)商品數(shù)據(jù)處理,這邊不做贅述。

    為了在組件文件中使用goods變量,需要定義getters:

    //新建一個getters.js文件,聲明getters
    const getters = {
      goods: state => state.shoppingBag.goods,
    };
    export default getters
    

    定義store的使用:

    // store.js文件
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    import shoppingBag from './shoppingBag'
    import getters from './getters'
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
      modules: {
        shoppingBag,
      },
      getters
    });
    
    export default store
    

    然后在vue項目的入口文件中需要在vue實例中使用我們聲明的store,示例如下:

    import Vue from 'vue'
    import router from './router'
    import store from './store'
    
    new Vue({
      el: '#app',
      router,
      store,
      template: '<App/>',
    })
    

    然后我們就可以在全局任何一個組件中用mapGetters在計算屬性中去獲取goods變量并使用,通過store的dispatch方法去觸發(fā)購物車的setGoods方法,更新購物車數(shù)據(jù):

    import {mapGetters} from 'vuex';
    
    export default {
        name:'test-component',
        computed: {
          ...mapGetters([
            'goods'
          ]),
        },
            methods:{
                //更新購物車數(shù)據(jù)
                updateGoods(){
                    let data = [];//新的購物車數(shù)據(jù)
                    this.$store.dispatch('setGoods',data);
                }
            }
    }
    
    

    以上就是通過vuex實現(xiàn)全局組件間數(shù)據(jù)通信的一個簡單流程介紹。

  1. 通過vue實例的事件映射和事件監(jiān)聽達到全局通信的效果:

    大家都知道父子組件通信時我們可以通過綁定事件監(jiān)聽,和子組件通過$emit事件映射,可以達到子組件到父組件的一個通信過程,利用這個方法,我們可以實現(xiàn)全局的一個事件的通信。示例如下:

    // 在main.js入口文件中聲明一個broadcast廣播示例,綁定在vue的原型上方便我們?nèi)质褂?Vue.prototype.$broadcast = new Vue();
    
    //在項目中示例一個發(fā)送廣播的組件
    export default {
        name:'send-message',
        mounted(){
            //在mounted生命周期發(fā)送一條廣播
            this.$broadcast.$emit('contact','你好');
    
        }
    }
    
    //在項目中示例一個發(fā)送廣播的組件
    export default {
        name:'get-message',
        destroyed() {
          this.$bus.$off('contact', this.getMessage);
        },
        mounted(){
            //在mounted生命周期進行監(jiān)聽
            this.$broadcast.$on('contact',this.getMessage);
        },
        methods:{
            getMessage(message){
                //收到消息做相關(guān)的業(yè)務(wù)處理
            }
        }
    }
    
    

    說明:通過$emit發(fā)送廣播事件時,進行相應(yīng)監(jiān)聽的組件都會收到消息并觸發(fā)綁定的函數(shù)方法。在這邊,我在組件的destoryed生命周期對綁定函數(shù)進行了解綁,如果不解綁的話,由于事件隊列相同事件名稱的綁定函數(shù)是一個數(shù)組,就算組件被銷毀,但是$broadcast這個實例未銷毀,在上面綁定的事件函數(shù)就是冗余的,會影響js代碼性能,所以在組件被銷毀后需及時進行解綁,否則可能會造成一些不可預(yù)料的系統(tǒng)bug。(此處“broadcast”只是一個命名,大家可以根據(jù)自己需要進行命名,常用的命名方式可能使用“bus”。盡量不要使用broadcast,可能會與vue內(nèi)置的一些屬性方法沖突)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。