示例 Component 之間的各種傳值方式-父子互傳(props/emit)、祖孫互傳(listeners/attr)、同輩互傳(eventBus)

適用:

  • Vue 2.x
  • 知道基本的 Vue.js 結構
  • 知道 Component 概念

# Demo

> CodeSandbox

(點左上角選單按鈕可以展開目錄欄,瀏覽檔案)


  • 本例 Components 組件引用關係:

    • a1 引入 b1 & b2

     
     


    <template>
        <b1/></b1>
        <b2/></c2>
    </template>
    
    • b1 引入 c1

     


    <template>
        <c1/></c1>
    </template>
    

# 往下傳:

# 1.父傳子 (props in)

  • a1 :引子組件時直接透過 v-bind 傳資料


     





     




    <template>
    	<b1 :textA1="textA1" />
    </template>
    <script>
    	data: () => {
            return {
                textA1: "A1",
            };
        },
    </script>
    
  • b1:定義 props 接收父層資料


     



     
     
     
     
     


    <template>
    	<p>{{ textA1 }}</p>
    </template>
    <script>
        props: {
            textA1: {
                type: String
            }
        }
    </script>
    

# 2.爺傳孫

# 2-1.透過父(props in x2)

  • a1 傳給子


     





     




    <template>
    	<b1 :textA1="textA1" />
    </template>
    <script>
    	data: () => {
            return {
                textA1: "A1"
            };
      },
    </script>
    
  • b1 再傳給子


     



     
     
     
     
     


    <template>
    	<c1 :textA1="textA1" />
    </template>
    <script>
    	props: {
            textA1: {
                type: String
            }
        }
    </script>
    
  • c1


     



     
     
     
     
     


    <template>
    	<p>{{ textA1 }}</p>
    </template>
    <script>
    	props: {
            textA1: {
                type: String
            }
      }
    </script>
    

# 2-2.不透過父(attr

  • a1 傳給子


     





     




    <template>
    	<b1 :textA2="textA2" />
    </template>
    <script>
    	data: () => {
            return {
                extA2: "A2",
            };
        }
    </script>
    
  • b1 引用子時使用 $v-bind="$attrs"


     


    <template>
    	<c1 v-bind="$attrs" />
    </template>
    
  • c1 透過 $attrs.XXX 取資料


     


    <template>
    	<p>{{ $attrs.textA2 }}</p>
    </template>
    

# 往上傳

# 3.子傳父 ( emit)

  • a1


     
     





     



     
     
     



    <template>
    	<b1 @emit-data="getChildData"/>
    	<p>{{ dataFromChild }}</p>
    </template>
    <script>
    	data: () => {
            return {
                dataFromChild: "",
            };
        },
    	methods: {
            getChildData(param) {
                this.dataFromChild = param;
            }
        }
    </script>
    
  • b1


     





     



     
     
     



    <template>
    	<button @click="dataToParent">傳資料給父層</button>
    </template>
    <script>
        data: () => {
            return {
                textB1: "B1",
            };
        },
        methods: {
            dataToParent() {
                this.$emit("emit-data", this.textB1);
            }
        }
    </script>
    

# 4.孫傳爺(emit / listeners

  • a1


     
     





     



     
     
     



    <template>
    	<b1 @getGrandSonData="getGrandSonData"/>
    	<p>{{ dataFromGrandSon }}</p>
    </template>
    <script>
    	data: () => {
            return {
                dataFromChild: ""
            };
        },
        methods: {
            getChildData(param) {
                this.dataFromChild = param;
            }
        }
    </script>
    
  • b1


     


    <template>
    	<c1 v-on="$listeners" />
    </template>
    
  • c1


     





     



     
     
     
     



    <template>
        <button @click="sendGrandSonData">傳資料給祖父層</button>
    </template>
    <script>
      data: () => {
            return {
                textC1: "C1",
            };
        },
        methods: {
            dataToParent() {
                this.$listeners.getGrandSonData(this.textC1);
                // 等同於 this.$emit("getGrandSonData", this.textC1);
            },
        }
    </script>
    

# 左右傳

# 5.傳兄弟 (eventBus)

  • 父層a1含b1、b2。b1要傳給b2


     
     


    <template>
    	<b1/></b1>
    	<b2/></c2>
    </template>
    
  1. eventBus:建立共用同一個事件機制-新增一個獨立的js檔 (例:eventBus.js)

    import Vue from 'vue';
    export default new Vue();
    
  2. 子組件 b1、b2 都引入 eventBus.js 檔


     


    <script>
    	import eventBus from "./../js/eventBus.js";
    </script>
    
  3. 子組件 b1 (要傳遞資料的)


     





     



     
     
     



    <template>
    	<button @click="dataToBrother">傳資料給兄弟</button>
    </template>
    <script>
        data: () => {
            return {
                textB1: "B1",
            };
        },
        methods: {
            dataToBrother() {
                eventBus.$emit("emit-data", this.textB1);
            }
        }
    </script>
    
  4. 子組件 b2(要接收資料的)


     





     



     


     
     
     
     
     



    <template>
    	<p>{{ dataFromBrother}}</p>
    </template>
    <script>
        data: () => {
            return {
                dataFromBrother: "",
            };
        },
        created: function () {
            this.getFromBrother();
        },
        methods: {
            getFromBrother() {
                eventBus.$on("emit-data", (param) => {
                    this.dataFromBrother= param;
                });
            }
        }
    </script>
    

# (參考資料)