本篇資料來于官方文檔:
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>