父子組件間的通信(在這裏父組件就是你自定義的標籤,子組件就是父組件template裏面的內容),父組件通過props選項向子組件傳遞參數或數據,子組件接收到參數後根據參數的不同來執行不同的操作。也就是說,在組件中使用props選項來聲明需要從父組件接受的數據(通俗點說就是,組件在註冊的時候通過props選項聲明子組件(template所指)需要從父組件中接受的數據),props選項的值可以是字符串數組或者對象:
值是字符串數組:
HTML部分:
<!-- (例1):父子通過props傳遞 -->
<my-component :message="msg" array="[1,2,3,4]"></my-component>
JS部分:
Vue.component("my-component",{
props:["message","array"],
// 子組件
template:"<div >{{message}}<div @click='changeVal'>{{message}}</div></div>",
})
注意:1.如果你直接在父組件上自定義屬性並且傳遞數字,布爾值,數組,對象,而不是使用v-bind在父組件上綁定屬性,傳遞的僅僅是字符串。如下面的例子:
HTML部分:
<my-component array="[1,2,3,4]"></my-component>
<!-- 9 -->
<my-component :array="dataArray"></my-component>
<!-- 4 -->
JS部分:
Vue.component("my-component",{
props:["message","array"],
// 子組件
template:"<div >{{message}}<div @click='changeVal'>{{message}}</div></div>",
data:function(){
return {
tips:"我來自data選項"
}
}
})
var myApp = new Vue({
el:"#container",
data:{
msg:"來自父組件上的數據",
dataArray:[1,2,3,4],
initMsg:"初始化數據"
}
})
2.同一個組件在複用的時候是相互獨立的
通過上例我們可以發現,無論是組件中data函數的返回值還是從父組件中傳遞過來的數據,子組件都能操作,那麼他們之間有何區別呢:
我個人感覺主要是作用域:props聲明的數據可能來自於Vue實例中的data選項,而data函數返回值,其作用域僅僅在於組件內部,是自己的私有數據。因此可以在data函數中將props數據作爲返回值保存起來,這樣以後你就可以隨意操縱數據了,也就避免了直接操縱父組件數據,從而影響父組件。
其實在Vue2.x中,通過props傳遞數據是單向的,也就是說,當父組件數據的變化會引起子組件數據的變化,但是反之不行,這也意味着,其實在子組件中無論你怎麼操作從props傳遞過來的數據,父組件的狀態都不會改變
爲了驗證這個想法,看下面的例子
HTML部分:
<div class="model">
<our-component :mero="initMsg"></our-component>
<input type="text" name="test" v-model = "initMsg">
<span>{{initMsg}}</span>
</div>
JS部分:
Vue.component("our-component",{
props:["mero"],
template:"<div @click='changeMSG'>{{mero}}</div>",
methods:{
changeMSG:function(){
alert(1)//this表示當前的組件our-component(可以視組件的地位和Vue實例的地位差不多)
this.mero = "我被改變啦!"
}
}
})
var myApp = new Vue({
el:"#container",
data:{
msg:"來自父組件上的數據",
dataArray:[1,2,3,4],
initMsg:"初始化數據"
}
})
結果:
初始化的時候是這樣的:
可以看到,span元素內的值一直都沒有變化,也就說明實例中的initMsg沒有發生改變,由於v-bind是雙向綁定的,所以父組件中對應的屬性沒有發生改變(雖然我們看不到),但即使是這樣也要注意:爲了安全起見,從父組件中傳遞過來的數據,要在組件的data選項中將其保存起來,或者利用計算屬性
說完了父組件向子組件傳遞數據,那麼子組件要向父組件傳遞數據該怎麼辦?其實子組件向父組件通信通過$emit()實現;
大意爲子組件使用了一個事件,比如click然後產生了一個效果(組件中methods選項中的函數做的事),然後將這樣的效果命名放入父組件(this.$emit(自定義事件名,[參數1]),[參數2]……),注意事件名要小寫字母,不要用駝峯命名法)中,當做一個事件來觸發,每當這樣的效果發生一次時,這樣父組件的事件也被觸發了(v-on給父組件綁定以上自定義事件),即可以產生另一種效果(一般操作的是Vue實例中的數據,隨意操作,可以傳參參數子組件中的數據,也可以不傳),這樣可以加強這兩個效果的緊密聯繫,並且這樣有趣又好用的方式也可以用在自己想要的地方。這樣當綁定在子組件上的事件觸發的時候,父組件上的事件也會觸發並執行一系列方法。
例如:
HTML部分
<div id="container" v-cloak>
<p>當前的值是:<span>{{total}}</span></p>
<!-- 給父組件綁定自定義事件 -->
<my-component
@increasefunc="changeTotal"
@decreasefunc="changeTotal"
></my-component></div>
JS部分:
// 自定義組件;
Vue.component("my-component",{
template:"\
<div>\
<button @click='increaseTotal'>add</button>\
<button @click='decreaseTotal'>reduce</button>\
</div>",
data:function(){
return{
counter:0
}
},
methods:{
increaseTotal:function(){
this.counter++;
console.log(this.counter)
// 同下
this.$emit("increasefunc",this.counter);
},
decreaseTotal:function(){
this.counter--;
console.log(this.counter);
// 定義自定義事件名,第一個參數是事件名,第二個參數及以後是要傳遞的數據
// 也可以不傳遞參數,事件名自定義
this.$emit("decreasefunc",this.counter)
}
}
})
var myApp = new Vue({
el:"#container",
data:{
total:0
},
methods:{
changeTotal:function(total){
// 形參total用來保存從子組件傳遞過來的數據的,也可以不傳參,
this.total++;
}
}
})
以上當點擊綁定在子組件上的click事件的時候,就會通過this.$emit()方法“告訴”父組件:子組件點擊了(事件被觸發了),那麼此時綁定在父組件上的對應的自定義事件也會觸發,並執行相應的函數changeTotal函數,實現了子組件和父組件事件的單向緊耦合