Vue實踐--父子組件間的通信(未完待續)

父子組件間的通信(在這裏父組件就是你自定義的標籤,子組件就是父組件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函數,實現了子組件和父組件事件的單向緊耦合






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章