天天看點

Vuejs——(10)元件——父子元件通信

本篇資料來于官方文檔:

http://cn.vuejs.org/guide/components.html#u7236_u5B50_u7EC4_u4EF6_u901A_u4FE1

本文是在官方文檔的基礎上,更加細緻的說明,代碼更多更全。

簡單來說,更适合新手閱讀

(二十七)父子元件通信

①通路子元件、父元件、根元件;

this.$parent    通路父元件

this.$children   通路子元件(是一個數組)

this.$root            根執行個體的後代通路根執行個體

示例代碼:

<div id="app">
    父元件:
    <input v-model="val"><br/>
    子元件:
    <test :test="val"></test>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            val: 1
        },
        components: {
            test: {
                props: ['test'],
                template: "<input @keyup='findParent' v-model='test'/>",
                methods: {
                    findParent: function () {
                        console.log(this.$parent);  //通路根元件
                        console.log(this.$parent.val);  //通路根元件的val屬性
                        console.log(this.$parent.$children.indexOf(this));  //檢視目前能否在其父元件的子元件中找到索引
                        console.log(this.$parent === this.$root);   //檢視父元件和根元件是不是全等的(因為他的父元件就是根元件)
                    }
                }
            }
        }
    });
</script>
           

當在子元件的輸入框按鍵彈起時,顯示内容依次為:

父元件、父元件的輸入框的值(預設情況是1)、0(表示是父元件的children屬性中的第一個元素)、true(由于父元件就是根元件,是以是全等的);

通過這樣的方法,可以在元件樹中進行互動。

②自定義事件:

首先,事件需要放置在events屬性之中,而不是放置在methods屬性中(新手很容易犯的錯誤),隻能觸發events屬性中的事件,而methods屬性中的事件是無法觸發的。

事件 說明
$on(事件名) 事件名的類型是字元串(下同),調用它可以通過this.$on()來調用;
$emit(事件名, 參數) 用于觸發事件,參數是用于傳遞給事件的參數。這個用于觸發同級事件(目前元件的)
$dispatch(事件名, 參數)

①向上派發事件,用于向父元件傳播。

②會首先觸發目前元件的同名事件(如果有);

③然後會向上冒泡,當遇到第一個符合的父元件的事件後觸發并停止;

④當父元件的事件的傳回值設為true會繼續冒泡去找下一個。

$broadcast(事件名, 參數)

①向下廣播事件,用于向所有子元件傳播。

②預設情況是僅限子元件;

③子元件事件的傳回值是true,才會繼續向該子元件的孫元件派發;

④不會觸發自身同名事件;

其次,向上派發和向下廣播有所差別:向上派發會觸發自身同名事件,而向下廣播不會;

第三,向上派發和向下廣播預設隻會觸發直系(子或者父,不包括祖先和孫)的事件,除非事件傳回值為true,才會繼續在這一條線上繼續。

第四,事件不能顯式的通過 this.事件名 來調用它。

示例代碼:

<div id="app">
    父元件:
    <button @click="parentClick">點選向下傳播broadcast</button>
    <br/>
    子元件1:
    <children1></children1>
    <br/>
    另一個子元件1:
    <another-children1></another-children1>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            val: 1
        },
        methods: {
            parentClick: function () {
                this.$broadcast("parentClick", "abc");
            }
        },
        events: {
            childrenClick: function () {
                console.log("childrenClick-Parent");
            },
            parentClick: function () {
                console.log("parentClick-Parent");
                return true;
            }
        },
        components: {
            children1: {    //這個無傳回值,不會繼續派發
                props: ['test'],
                template: "<button>children1</button></br>子元件2:<children2></children2>",
                events: {
                    childrenClick: function () {
                        console.log("childrenClick-children1");
                    },
                    parentClick: function (msg) {
                        console.log("parentClick-Children1");
                        console.log("message:" + msg);
                    }
                },
                components: {
                    children2: {
                        props: ['test'],
                        template: "<button @click='findParent'>children-Click</button>",
                        methods: {
                            findParent: function () {
                                this.$dispatch('childrenClick');
                            }
                        },
                        events: {
                            childrenClick: function () {
                                console.log("childrenClick-children2");
                            },
                            parentClick: function (msg) {
                                console.log("parentClick-Children2");
                                console.log("message:" + msg);
                            }
                        }
                    }
                }
            },
            anotherChildren1: { //這個是傳回值為true,會繼續向子元件的子元件派發
                props: ['test'],
                template: "<button>anotherChildren1</button></br>另一個子元件2:<another-children2></another-children2>",
                events: {
                    childrenClick: function () {
                        console.log("childrenClick-anotherChildren1");
                        return true;
                    },
                    parentClick: function (msg) {
                        console.log("parentClick-anotherChildren1");
                        console.log("message:" + msg);
                        return true;
                    }
                },
                components: {
                    anotherChildren2: {
                        props: ['test'],
                        template: "<button @click='findParent'>anotherChildren2-Click</button>",
                        methods: {
                            findParent: function () {
                                this.$dispatch('childrenClick');
                            }
                        },
                        events: {
                            childrenClick: function () {
                                console.log("childrenClick-anotherChildren2");
                            },
                            parentClick: function (msg) {
                                console.log("parentClick-anotherChildren2");
                                console.log("message:" + msg);
                            }
                        }
                    }
                }
            }

        }
    });
</script>
               },
                            parentClick: function () {
                                console.log("parentClick-anotherChildren2");
                            }
                        }
                    }
                }
            }

        }
    });
</script>
           

說明:

【1】點選父元件的按鈕,會向下廣播,然後觸發子元件1本身,另外一個子元件1,以及另一個子元件2;

【2】點選子元件2的按鈕,會觸發子元件2的事件和子元件1的事件,但不會觸發父元件的按鈕;

【3】點選另一個子元件2的按鈕,會觸發另一個子元件2的事件,另一個子元件1的事件和父元件的事件(因為另一個子元件1的事件的傳回值為true);

③使用v-on綁定自定義事件:

【1】簡單來說,子元件觸發某個事件(events裡的方法)時,父元件也會執行某個方法(父元件methods裡的方法)。

【2】觸發的綁定寫在模闆之中(即被替換的那個template模闆中),可以多個子元件的事件綁定一個父元件的方法,或者不同子元件的事情綁定不同父元件的方法,但是不能同一個子元件事件綁定多個父元件的方法。

【3】子元件派發消息傳遞的參數,即使子元件的事件沒有參數,也不影響将參數傳遞給父元件的方法(即父元件的方法可以接受到子元件方法擷取的參數)

如示例:

<div id="app">
    父元件:
    <button>點選向下傳播broadcast</button>
    <br/>
    子元件1:
    <!--綁定寫在這裡,可以多個綁定同一個,或者不同綁定不同的,但不能一個綁定多個-->
    <children v-on:test="parent" @test2="another"></children>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            val: 1
        },
        methods: {
            parent: function (arg) {
                console.log(arg);
                console.log("the first method with test event");
            },
            another: function () {
                console.log("another method");
            }
        },
        components: {
            children: {    //這個無傳回值,不會繼續派發
                props: ['test'],
                template: "<button @click='childClick'>children1</button></br><button @click='childClick2'>children1</button>",
                methods: {
                    childClick: function () {
                        this.$emit("test", 'the argument for dispatch');
                    },
                    childClick2: function () {
                        this.$emit("test2");
                    }
                },
                events: {
                    test: function () {
                        console.log("test");
                    },
                    test2: function () {
                        console.log("test2");
                    }
                }
            }
        }
    });
</script>
           

④子元件索引

簡單來說:就是可以直接從索引擷取到子元件,然後就可以調用各個子元件的方法了。

添加索引方法是:在标簽裡添加v-ref:索引名

調用元件方法是:vm.$ref.索引名

也可以直接在父元件中使用this.$ref.索引名

這個時候,就可以獲得元件了,然後通過元件可以調用他的方法,或者是使用其資料。

示例代碼:

<div id="app">
    父元件:
    <button @click="todo">觸發子元件的事件</button>
    <br/>
    子元件1:
    <!--綁定寫在這裡,可以多個綁定同一個,或者不同綁定不同的,但不能一個綁定多個-->
    <children v-ref:child></children>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        methods: {
            todo: function () {
                this.$refs.child.fromParent();  //通過索引調用子元件的fromParent方法
            }
        },
        components: {
            children: {    //這個無傳回值,不會繼續派發
                props: ['test'],
                template: "<button>children1</button>",
                methods: {
                    fromParent: function () {
                        console.log("happened fromParent by ref");
                    }
                }
            }
        }
    });
</script>
           
上一篇: Vuejs安裝