組件化思想是vue框架里面極具重要的一種思想,使用組件可以在我們的項目之中更好的搭建整體布局狂芋,從而輕松的使用少量的代碼完成大量的工作。
父組件向子組件傳值
父組件向子組件進(jìn)行傳值,使用的是綁定一個屬性的方式没炒。我們先看一個例子:
<todo-item v-bind:content = '1'>
</todo-item>
我們定義了一個模板如下:
var TodoItem = {
props: ['content' ], //子組件接收父組件的傳值
template: "<li>{{content}}</li>"
}
這是最簡單的父組件向子組件傳值,父組件綁定了一個屬性犯戏,其名為content(這里content是我們自己定義的送火,你也可以之間使用已經(jīng)定義好的屬性,比如title)先匪,而它所攜帶的參數(shù)為數(shù)字1漾脂,這個1是number類型
這里我們需要注意一個重點,就是我們在父組件里面綁定屬性用的是v-bind胚鸯,你也可以不使用v-bind骨稿,直接寫content='1',他倆的區(qū)別在于姜钳,直接寫屬性名后跟屬性值坦冠,這個屬性值只能是字符串類型,而使用v-bind綁定參數(shù)哥桥,而后跟的可以不僅僅是字符串辙浑,可以是任意類型
到現(xiàn)在為止父組件只需要做這么一件事即可,接下來子組件需要去獲取到父組件傳出來的數(shù)據(jù)
我們在子組件里面獲取數(shù)據(jù)需要用到props來接收拟糕,其后面可以接收多個數(shù)據(jù)判呕,當(dāng)我們接收到數(shù)據(jù)之后,就可以直接使用這個傳出來的content了
- 另外需要注意的地方在于送滞,vue規(guī)定子組件對于數(shù)據(jù)只有使用權(quán)不可以修改數(shù)據(jù)侠草,因為可能有多個子組件接收父組件傳出來的數(shù)據(jù),如果這個數(shù)據(jù)是引用數(shù)據(jù)犁嗅,那么有一個子組件修改了數(shù)據(jù)边涕,勢必影響其他的子組件,如果非要修改,我們可以使用一個變量拷貝接收的數(shù)據(jù)
子組件向父組件傳值
子組件向外傳出數(shù)據(jù)需要用到$emit
這里我們直接先放上例子功蜓,我就直接附上了完整的html代碼
<body>
<div id="root">
<ul>
<!--v-bind是父組件向子組件傳值园爷,簡寫方法直接寫冒號即可
這里@click是父組件監(jiān)聽子組件傳出來的click事件,如果發(fā)現(xiàn)了子組件拋出的click事件式撼,就會觸發(fā)后面的itemClick函數(shù)-->
<todo-item :content = '1' @click="itemClick"></todo-item>
</ul>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('TodoItem' , {
props: ['content'], //子組件接收父組件的傳值
template: "<li @click='handleItemClick'>{{content}}</li>",
methods: {
handleItemClick: function(){
//點擊子組件的時候童社,會向外拋出一個click事件,$emit用于向外拋出事件著隆,后面可以跟一個或多個參數(shù)叠洗,用于傳值
this.$emit("click" , this.content)
}
}
})
var vm = new Vue({
el: '#root',
methods: {
//形參value是用來接收事件觸發(fā)的時候傳過來的參數(shù),就是$emit后面攜帶的參數(shù)
itemClick: function(value){
alert(value)
}
}
})
</script>
這段代碼的功能是點擊元素的時候旅东,會彈框顯示里面的內(nèi)容
大體思路就是灭抑,
- 一開始定義模板的時候,就已經(jīng)綁定了會觸發(fā)handleItemClick函數(shù)的點擊事件
- 當(dāng)我們點擊li標(biāo)簽的時候抵代,觸發(fā)該函數(shù)腾节,通過$emit方法向外拋出一個名為click的事件
- 我們在父組件里面進(jìn)行監(jiān)聽,如果發(fā)現(xiàn)了click事件荤牍,就會觸發(fā)后面的itemClick事件案腺,并執(zhí)行里面的回調(diào)函數(shù),打印里面的值
非父子組件傳值
- 這里建議父子組件已經(jīng)掌握的同學(xué)康吵,再對非父子組件進(jìn)行學(xué)習(xí)
我們先附上例子劈榨,這樣比較方便上下文查看,所以我依然附上完整代碼晦嵌,建議大家比著思路一點一點敲出來同辣,盡量不要復(fù)制粘貼
<body>
<div id="root">
<child content='Dell'></child>
<child content='Leo'></child>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//在vue的原型上面定義一個bus并讓其等于vue的實例,vue是一個函數(shù)惭载,所以它有原型鏈旱函,這樣任意一個vue實例都可以使用bus屬性
Vue.prototype.bus = new Vue()
Vue.component('child' , {
props:['content'],
//這里有一個重點,組件里面使用的data必須是一個函數(shù)描滔,且必須返回一個對象棒妨,所用到的數(shù)據(jù)都在該對象里面
//下面這句話的意思就是我們把接收到的數(shù)據(jù)進(jìn)行了拷貝,讓selfContent等于當(dāng)前content的值
data: function(){
return {
selfContent: this.content
}
},
template: '<div @click="handleClick">{{selfContent}}</div>',
methods: {
handleClick: function(){
//通過實例自身的bus方法向外觸發(fā)change事件含长,并攜帶了selfContent參數(shù)
this.bus.$emit('change' , this.selfContent)
}
},
//生命周期鉤子券腔,頁面掛載后立即觸發(fā)
mounted: function(){
//綁定當(dāng)前組件對象,回調(diào)函數(shù)執(zhí)行的時候this指向會改變
let that = this
//對事件進(jìn)行監(jiān)聽拘泞,$on可以對事件進(jìn)行監(jiān)聽纷纫,監(jiān)聽bus的改變,$emit用于向外觸發(fā)事件田弥,$off用于取消自定義事件監(jiān)聽器
//bus是組件定義的實例涛酗,所以每個組件都會有bus屬性,而bus是實例偷厦,所以它也會有$on方法
this.bus.$on('change' , function(msg){
//讓組件中的selfContent全部等于傳進(jìn)來的參數(shù)
that.selfContent = msg
})
}
})
var vm = new Vue({
el: '#root'
})
</script>
這段代碼的作用是商叹,頁面中的兩個元素是兄弟元素,當(dāng)我們點擊其中一個元素的時候只泼,其他標(biāo)簽里面的值會和當(dāng)前點擊的標(biāo)簽里面的值相等
我來講一下實現(xiàn)原理:父組件兩個child組件是屬于兄弟元素剖笙,我們想要他們之間進(jìn)行數(shù)值互傳。
- 所以我們先定義一個bus方法讓其在vue原型上面请唱,這樣只要是vue實例都可以使用該方法弥咪。
- 然后我們在模板綁定點擊事件,當(dāng)元素點擊時觸發(fā)handleClick函數(shù)十绑,當(dāng)handleClick點擊事件觸發(fā)的時候聚至,執(zhí)行回調(diào)函數(shù),向外拋出change事件本橙,并傳出去從父組件接收到的參數(shù)扳躬,selfContent
- 緊接著我們使用生命周期鉤子,mounted甚亭,它會在頁面掛載之后觸發(fā)
- 所有的組件都會調(diào)用$on監(jiān)聽bus的改變贷币,如果發(fā)現(xiàn)change事件,立即調(diào)用回調(diào)函數(shù)亏狰,并對$emit傳出來的參數(shù)進(jìn)行接收
- 最后執(zhí)行函數(shù)即可
純原創(chuàng)役纹,如果有錯誤,歡迎指正暇唾,我一定及時修改 =^=