一勿决、組件
組件茫船,可以說是現代前端框架中必不可少的組成部分琅束。使用組件,不僅能極大地提高代碼的復用率和開發(fā)者的開發(fā)效率算谈,對于代碼后期的維護也有著非常重要的意義涩禀。前端開發(fā),由于歷史遺留原因然眼,WebComponent 雖然好用艾船,但其發(fā)展情況卻受到極大地限制,和很多新興的前端技術一樣高每,可望而不可即屿岂。基于這樣的情況鲸匿,聰明的開發(fā)者們嘗試通過框架內部集成相應的功能來完成組件化爷怀,各種現代前端框架基本上都有各自的實現。這里我們來分析一下 vue 的組件晒骇,重點關注數據的流向霉撵。
二磺浙、vue 組件
vue 的組件,創(chuàng)建模板的時候是基于普通的 html 的徒坡,不需要學習 jsx撕氧、handlebars 等的特殊語法,所以相對來說喇完,學習成本比較低伦泥,更容易上手。使用 vue 組件的時候锦溪,一般分為組件注冊和組件調用兩個部分不脯。
(一)組件注冊
Vue.component('pop-box', {
template: '<div class="component-box">\
<div class="component-content">\
..........
</div>\
</div>',
props: [...],
data: function () {
return ...;
},
methods: {
...
},
mounted () {
...
},
...
});
利用 Vue.component
方法我們可以很輕松的創(chuàng)建一個全局可用的組件,當然也可以在實例或組件內部注冊局部組件刻诊,但原理大同小異防楷。Vue.component
的第一個參數是組件的名字,或者說唯一標識符(id)则涯,后續(xù)調用它將通過這個名字進行調用复局;第二個參數是一個對象,通常它包含了模板(template)粟判、組件內維護的數據(data亿昏、computed)、方法(methods)档礁、鉤子函數(created 角钩、 mounted...)等關鍵信息。
值得注意的是:
- 組件內的 data 必須是一個函數呻澜,它的返回值將作為實際的 “data”递礼;
- vue1.x 和 vue2.x 的鉤子函數略有不同,如果發(fā)現鉤子函數不生效易迹,記得確認 vue 的版本宰衙。
(二)組件調用
(1)開始標簽 + 結束標簽模式
<pop-box text="200" v-bind:number="200"></pop-box>
(2)無結束標簽模式
<pop-box text="200" v-bind:number="200" />
調用 vue 組件有以上兩種模式。兩種模式上睹欲,如果沒有使用 slot
那么實際上并沒有任何區(qū)別供炼,但如果需要使用 slot
的時候,便只能使用同時包含開始標簽和結束標簽的模式窘疮。
值得注意的是袋哼,上面綁定數據的時候,直接采用 property="value"
的形式闸衫,不管 value
是數字還是字符串涛贯,property
最終都是字符串類型。如果想讓其變成數字類型蔚出,請使用 v-bind:property="value"
的形式弟翘,或者簡寫為 :property="value"
虫腋。
三、vue 組件數據流
vue 遵循了典型的單向數據流的原則稀余,即數據總是由父組件傳遞到子組件悦冀,子組件在其內部可以有自己維護的數據,但它無權修改父組件傳遞給它的數據睛琳,當開發(fā)者嘗試這樣做的時候盒蟆,vue 將會報錯。這樣做的好處是师骗,防止多個子組件都嘗試修改父組件狀態(tài)時历等,讓這一行為變得難以追溯。vue 中具體實現方式如下:
父組件通過綁定 props 的方式辟癌,將數據傳遞給子組件寒屯,但是子組件自己并沒有權利修改這些數據,如果要修改愿待,只能把修改這一個行為通過 event 的方式報告給父組件浩螺,由父組件本身決定該如何處理數據。
(一)簡單實例
<div id="app">
<my-counter @inc="increase" :counter="counter"></my-counter>
</div>
...
Vue.component('my-counter', {
template: '<div class="counter">\
<div>{{counter}}</div>\
<button @click="inc">increase</button>\
</div>',
props: ['counter'],
methods: {
inc: function () {
this.$emit('inc');
}
}
});
var app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increase () {
this.counter ++;
}
}
});
為了顯得更簡單這里只創(chuàng)建了一個 my-counter
組件作為子組件仍侥,我們可以姑且將 vue 的實例認為是一個父組件。點擊這里查看 demo
(二)分析數據流向分析
- (1)我們在父組件中定義了一個數據叫
counter
鸳君; - (2)調用組件的時候农渊,通過
:counter="counter"
的方式,將父組件的counter
以prop
的方式傳遞到子組件中或颊; - (3)子組件讀取到
counter
砸紊,并將其展示在模板中; - (4)用戶點擊按鈕囱挑,
counter
需要增加醉顽; - (5)子組件監(jiān)聽到這個事件,但它并不直接修改
counter
平挑,而是通過this.$emit('inc');
以自定義事件的形式游添,將需要增加的這一個事件報告給父組件; - (6)父組件中通熄,由于通過執(zhí)行過
@inc="increase"
唆涝,能夠監(jiān)聽到子組件報告過來的事件,并在自己的increase
方法中唇辨,實現counter
的增加廊酣; - (7)父組件里的數據更新了,子組件里的數據也將自動更新赏枚,同時也將更新界面內容亡驰,這一過程由框架自動完成晓猛。
(三)總結
上面這一個示例,基本完整展示了 vue 主要的數據流向凡辱,但是這種基于 prop/evnet 的方式僅適用于存在直接的父子關系的組件戒职,兄弟組件或者大量組件的數據流向如果再基于這種方式將會變得非常麻煩,這時可以考慮使用更加強大的狀態(tài)管理模式煞茫。