Vue2.0筆記——組件2
父子組件的通信
組件 A 在它的模板中使用了組件 B。它們之間必然需要相互通信:父組件可能要給子組件下發數據,子組件則可能要將它內部發生的事情告知父組件。
首先,需要在Vue實例裏定義一個組件,設置data,然後在這個組件裏再添加一個conponents選項,註意不要添錯位置。
示例:
<div id="app"> <my-father></my-father> </div> //父組件的模板 <template id="fatherTl"> <div> <p>這是父組件</p> <p>訪問父組件數據:{{name}},{{age}},姓名:{{user.name}},年齡:{{user.age}}</p> <my-child></my-child> </div> </template> //子組件的模板 <template id="childTl"> <div> <p>這是子組件</p> <p>訪問子組件數據:性別:{{sex}},身高:{{height}}</p> </div> </template>
var vm = new Vue({ el:‘#app‘, components:{ ‘my-father‘:{ template:‘#fatherTl‘, data:function(){ return { name:‘Xiao‘, age:19, user:{name:‘小冪冪‘,age:31} } }, components:{ ‘my-child‘:{ template:‘#childTl‘, data:function(){ return { height:166, sex:‘Female‘ } } } } } } });
作為子組件my-child,<my-child></my-child>標簽應放在父組件標簽<my-father></my-father>標簽內,而不能是實例掛載元素下。
如果你嘗試直接在父組件模板或子組件模板中通過{{}}模板語法引用則會出現錯誤。
運行此案例,完美運行,你可以通過vue-devtool查看組件結構圖。
目前還沒有通信,只是顯示了一下各自的數據,接下來傳遞數據了。
父向子傳遞數據
父向子傳遞數據,我們需要做的就是將要傳遞的數據綁定到子組件的標簽上,並在子組件內通過props選項來接收。
//father模板中添加 <my-child :childName="user.name" :age="user.age"></my-child> //接著,在my-child組件中添加選項 props:[‘childName‘,‘age‘] //最後,我們引用name和age //my-child模板中 <div> <p>這是子組件</p> <p>訪問子組件數據:性別:{{sex}},身高:{{height}}</p> <p>訪問父組件數據:{{childName}},{{age}}</p>//添加了這一條 </div>
接下來訪問,即可看到數據顯示了。
分析一下,:name和:age,這個冒號“:”後的name和age,就是,props中接收的屬性名,將作為子組件的屬性名,就是說這兩個名可以改,無論改成什麽,最後都需要通過這個名字訪問。
而屬性值就是引號中的user.name,user.age,它直接也是父組件的屬性名。
子向父傳遞數據
子向父傳遞書序需要通過事件的方式向上傳遞數據。要做的就是通過$emit方法觸發事件,並添加附加參數(就是屬性),通過事件傳遞數據,父組件中的事件方法接收這參數即可。
示例:
//my-child模板中定義一個按鈕,作為媒介,用來觸發
<button @click="send">向上傳遞給父組件數據</button>
//組組件定義
methods:{
send(){
this.$emit(‘child-up‘,this.sex,this.height);
}
}
//my-father組件模板中監聽這個事件
<my-child :name="user.name" :age="user.age" @child-up="getData"></my-child>
//所以你需要在my-father組件中定義這個getData方法來接收
//但你需註意,你必須提前初始化這些屬性
methods:{
getData(sex,height){
this.sex=sex;
this.height=height;
}
}
//myfather模板中
<h3>訪問子組件數據,{{sex}},{{height}}</h3>
這樣,通過某個媒介(點擊或其他方式)作為觸發事件的方式,來傳遞數據,並在該實例處監聽該事件,並接收數據。
此處將監聽在my-child標簽中,因my-chlid標簽作為myfather標簽的子組件,所以將getData方法定義在父組件methods中。
單向數據流
props 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是反過來不會。這是為了防止子組件無意間修改了父組件的狀態,來避免應用的數據流變得難以理解。
另外,每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味著你不應該在子組件內部改變 prop。如果你這麽做了,Vue 會在控制臺給出警告。
接下來我們想試著修改父組件內屬性的值,看看是不是會跟著修改,且如果修改prop中屬性是否會出現錯誤。
示例:
代碼較多,我們再新建一個html。我們只註冊使用一個組件,因為Vue實例本身也是一個組件,它是根組件,所以在實例中components中註冊一個組件作為子組件。
<div id="app">
<p>父組件:{{age}}</p>
<p><input type="text" v-model="name"></p>
<hr/>
<my-component :username="name" :age="age"></my-component>
</div>
<template id="templ">
<p>子組件中父組件的數據,{{username}}</p>
</template>
var vm = new Vue({
el:‘#app‘,
data:{
name:‘XiaoYao‘,
age:19
},
components:{
‘my-component‘:{
template:‘#templ‘,
props:[‘username‘,‘age‘]
}
}
});
我們已經通過props屬性進行向下傳遞數據了,父組件中我們把name屬性設置為雙向綁定的屬性,以便於修改。
接下來直接在文本框中修改name的值,子組件模板中,值就跟著變了。
那麽,我們開始嘗試著修改它。
示例:
//在組件模板中添加如下按鈕。註意模板中只有一個根元素,需要div包起來
<button @click="change">直接修改父組件傳遞下來的值</button>
//在子組件中定義方法,註意不要寫錯位置,會發生錯誤的
methods:{
change(){
this.username=‘I Love You‘;//直接修改它的值
}
}
運行結果,瀏覽器控制臺發生異常了。
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop‘s value. Prop being mutated: "username"
由此可見,它是不可以更改的,因為它是自動更新值的。
如果你很需要在子組件中修改它的話
當然如果非要這麽做的話,也還是有方法的,因為你很有必要用它。
- 你可能希望把它當做局部變量處理
- 你可能需要得到它的值顯示出來,並修改它
那麽你有兩種選擇,
- 一種是定義局部變量,來操作它。
- 另一種就是定義計算屬性,依據原值的修改來動態的改變這個計算屬性,而你使用的就是這個計算屬性
接下來我們只需要這樣:
//1.添加屬性,並將傳來的屬性復制給新的局部定義屬性
data:function(){
return {
myName:this.username
}
}
//2.接下來要改變和使用的值就都是myName了
methods:{
change(){
this.myName=‘I Love you‘
}
}
//模板中
<p>子組件中父組件的數據,{{myName}}</p>
對於使用計算屬性,我們可以做:
props: [‘size‘],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
//接下來就是使用normalizedSize屬性顯示了
以上是單項數據流的問題,如果需要雙向呢,看下面。
雙向數據流,父子雙向綁定
我們使用.sync修飾符,該修飾符在1.0中使用,在2.0中廢除,後又在2.3中重新引用,只是錯了稍加修改,具體情況看官網。
//父組件向下傳遞時,子組件標簽上傳遞的屬性後面添加.sync修飾符
<my-component :username.sync="name" :age="age"></my-component>
然後需要顯式的觸發一個更新事件。
methods:{
change(){
this.$emit(‘update:username‘, ‘I Love You‘);
//this.username=‘I Love you‘;
}
}
通過$emit事件方法,然後第一個參數,update:是固定寫法,後面是新屬性值,這樣就可以雙向綁定了。使用按鈕觸發不是必需的,只要在某處調用這個觸發方法即可。
假如你向下傳遞的是對象,那麽如果要修改的話會更方便。
我們可以直接修改對象的屬性值而不需要.sync修飾符。
//為父組件定義一個對象,並且顯示他
emp:{salary:6000,workingAge:2,name:‘XiaoChenchen‘}
<p>父組件emp:{{emp}}</p>
//在單擊按鈕方法中直接設置對象的屬性值
this.emp.salary=8000;
單擊按鈕,發現salarys從6000變成了8000,而且不會不會發生任何錯誤。
這是因為對象的引用地址沒有發生改變,改變的只是裏面的屬性,屬性改變並不會影響對象地址。
所以我們建議封裝成對象更方便,但有時也是需要到.sync修飾符的,主要是看情況了。
謝謝觀看,下節繼續講組件,非父子間通信,以及slot插槽分發。
愛自己,更愛需要愛的人。。。
Vue2.0筆記——組件2