vue就地复用不是更快吗_Vue.js从零开始——组件(1)
其實(shí)本來(lái)應(yīng)該把這個(gè)章節(jié)也放在入門(mén)里面的,但是想想這個(gè)部分是 Vue 的核心功能之一,所以就獨(dú)立出來(lái)吧,專(zhuān)門(mén)進(jìn)行介紹也挺好的。
這個(gè)章節(jié)主要是對(duì) Vue 的組件(Component)有個(gè)基礎(chǔ)的了解先,也就是組件的入門(mén)。
1 概念
組件是 Vue.js 最強(qiáng)大的功能之一,它可以擴(kuò)展 HTML 元素,封裝可重用的代碼。
組件系統(tǒng)讓我們可以用獨(dú)立可復(fù)用的小組件來(lái)構(gòu)建大型應(yīng)用,幾乎任意類(lèi)型的應(yīng)用的界面都可以抽象為一個(gè)組件樹(shù):
官網(wǎng)的圖,蠻形象的因?yàn)樗蓮?fù)用,所以并不在 HTML 里面定義,而是首先在 Vue 代碼中注冊(cè)一個(gè)名字,格式如下:
VuetagName 為組件名,options 為配置選項(xiàng),完成后,我們可以在 HTML 當(dāng)中使用以下方式來(lái)調(diào)用組件:
<1.1 使用
下面是個(gè)例子:
<!DOCTYPE html>上面的代碼為了方便查看,我把 <script> 的部分統(tǒng)一放在了 <div> 下面,從邏輯上面發(fā)生的順序,可以理解為,先注冊(cè)了組件 button-counter,然后在 <div> 當(dāng)中引用,最后創(chuàng)建這個(gè) <div> 的實(shí)例,從而使得組件發(fā)生作用。
因?yàn)榻M件是可復(fù)用的 Vue 實(shí)例,所以它們與 new Vue 接收相同的選項(xiàng),例如 data、computed、watch、methods 以及生命周期鉤子等;僅有的例外是像 el 這樣根實(shí)例特有的選項(xiàng)。
1.2 復(fù)用
組件的誕生,其初衷就是為了能夠復(fù)用,所以只要在 Vue 當(dāng)中注冊(cè)了組件,之后在 HTML 當(dāng)中使用幾次都是可行的,譬如:
<這里代碼當(dāng)中調(diào)用了 4 次,于是就出現(xiàn)了 4 個(gè)完全相同的按鈕,當(dāng)然功能上也是一致的:當(dāng)點(diǎn)擊按鈕時(shí),每個(gè)組件都會(huì)各自獨(dú)立維護(hù)它的 count;因?yàn)槊坑靡淮谓M件,就會(huì)有一個(gè)它的新實(shí)例被創(chuàng)建。
1.3 與 Vue 實(shí)例的區(qū)別
前面提到過(guò),組件和 Vue 實(shí)例可以接受相同的選項(xiàng),這里主要看看它和實(shí)例關(guān)鍵的不同之處:
- 沒(méi)有 el 選項(xiàng):這是因?yàn)榻M件不需要事先綁定到對(duì)應(yīng)的 HTML 元素,而是在創(chuàng)建后,再到 HTML 當(dāng)中調(diào)用;
- data 必須是個(gè)函數(shù):這樣,每個(gè)實(shí)例就可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝,否則組件的復(fù)用就無(wú)法成立了,因?yàn)樗媒M件之間將會(huì)互相影響,比如上面的例子,可能會(huì)變成這樣:
當(dāng)然為了避免這種情況,Vue 對(duì)此做了一點(diǎn)限制,如果組件的 data 不是一個(gè)函數(shù)的時(shí)候,組件本身將無(wú)法使用,比如這樣:
Vue瞧,Vue 直接報(bào)錯(cuò)了,而且寫(xiě)的很清楚:The "data" option should be a function...。
2 組件的注冊(cè)
一個(gè)網(wǎng)頁(yè)應(yīng)用,是需要有很多結(jié)構(gòu)的,如果還記得之前 CSS 部分的網(wǎng)格布局,我們就應(yīng)該了解到大部分的頁(yè)面都是需要類(lèi)似結(jié)構(gòu)的,我們可以直接轉(zhuǎn)化為各個(gè)組件,例如,可能會(huì)有頁(yè)頭、側(cè)邊欄、內(nèi)容區(qū)等組件,每個(gè)組件又包含了其它的像導(dǎo)航鏈接、Wiki 之類(lèi)的組件。
為了能在模板中使用,這些組件必須先注冊(cè)以便 Vue 能夠識(shí)別。這里有兩種組件的注冊(cè)類(lèi)型:全局注冊(cè)和局部注冊(cè)。
前面一節(jié),我們的組件都只是通過(guò) Vue.component 全局注冊(cè)的:
Vue就先從這一部分開(kāi)始了解注冊(cè)組件的一些細(xì)節(jié):
2.1 組件名
在注冊(cè)一個(gè)組件的時(shí)候,我們始終需要給它一個(gè)名字,也就是組件注冊(cè)的第一個(gè)參數(shù)。
給予組件的名字依賴于我們打算拿它來(lái)做什么:當(dāng)直接在 DOM 中使用一個(gè)組件 (而不是在字符串模板或單文件組件) 的時(shí)候,我們強(qiáng)烈推薦遵循 W3C 規(guī)范中的自定義組件名 (字母全小寫(xiě)且必須包含一個(gè)連字符,即 kebab-case,例如 my-component-name),這會(huì)幫助我們避免和當(dāng)前以及未來(lái)的 HTML 元素相沖突。
官方推薦的風(fēng)格指南中,可以查閱到關(guān)于組件名的其它建議。
當(dāng)然,我們也可以使用首字母大寫(xiě)的格式,即 PascalCase,例如 MyComponentName,但是這種命名方式,在 HTML 當(dāng)中依然要使用 my-component-name 來(lái)進(jìn)行調(diào)用,因?yàn)楸容^違反直覺(jué),所以我個(gè)人不是很建議。
2.2 全局注冊(cè)
全局注冊(cè),也就是說(shuō)它們?cè)谧?cè)之后可以用在任何新創(chuàng)建的 Vue 根實(shí)例 (new Vue) 的模板中,比如官網(wǎng)上的例子:
Vue:
VueHTML:
<在所有子組件中也是如此,也就是說(shuō)這三個(gè)組件在各自內(nèi)部也都可以相互使用。
因?yàn)榍懊嬉呀?jīng)講述過(guò)很多相關(guān)內(nèi)容,這部分就簡(jiǎn)化一下,到此為止。
2.3 局部注冊(cè)
全局注冊(cè)往往是不夠理想的。比如,如果使用一個(gè)像 webpack 這樣的構(gòu)建系統(tǒng),全局注冊(cè)所有的組件意味著即便我們已經(jīng)不再使用一個(gè)組件了,它仍然會(huì)被包含在最終的構(gòu)建結(jié)果中。這造成了用戶下載的 JavaScript 的無(wú)謂的增加。
在這些情況下,我們可以通過(guò)一個(gè)普通的 JavaScript 對(duì)象來(lái)定義組件:
let然后,在 components 選項(xiàng)當(dāng)中定義需要使用的組件:
letcomponents 對(duì)象中的屬性名就是自定義元素的名字,它的值就是這個(gè)組件的選項(xiàng)對(duì)象。
下面是個(gè)例子,還用之前那個(gè)按鈕的例子進(jìn)行修改:
<!DOCTYPE html> 就不用gif了,因?yàn)樾袨槟J胶椭暗睦右粯?p>上面的代碼聲明了一個(gè) customComp 對(duì)象,它的內(nèi)容就和之前進(jìn)行全局注冊(cè)組件是一樣的,此時(shí),我們?cè)?app 這個(gè)實(shí)例當(dāng)中將該對(duì)象注冊(cè)到其內(nèi)部,并指定了一個(gè)和原先一樣的組件名,所以在 HTML 當(dāng)中無(wú)需修改即可調(diào)用了。局部注冊(cè)和全局注冊(cè)的最大不同是,局部注冊(cè)的組件在其子組件中不可用。
例如,如果需要 ComponentA 在 ComponentB 中可用,我們要這樣寫(xiě):
let或者我們使用 ES 2015 后引入的模塊(module),可以這樣寫(xiě):
import這里要留意,在 ES 2015+ 中,在對(duì)象中放一個(gè)類(lèi)似 ComponentA 的變量名其實(shí)是 ComponentA: ComponentA 的縮寫(xiě),即這個(gè)變量名同時(shí)是:
- 用在模板中的自定義元素的名稱(chēng)
- 包含了這個(gè)組件選項(xiàng)的變量名
有關(guān)于模塊方面的相關(guān)知識(shí),我會(huì)考慮在后面單獨(dú)成章來(lái)組織一下,今天先了解到這里就夠了。
3 向子組件傳遞數(shù)據(jù)
之前在第2節(jié)的開(kāi)頭,我們提到了頁(yè)面應(yīng)用上可能存在 Wiki 組件的事情,問(wèn)題是如果不能向這個(gè)組件傳遞某一篇 Wiki 的標(biāo)題或內(nèi)容之類(lèi)的我們想展示的數(shù)據(jù)的話,它是沒(méi)有辦法使用的。
這就是 Vue 當(dāng)中 prop 的由來(lái):prop 是可以在組件上注冊(cè)的一些自定義屬性,當(dāng)一個(gè)值傳遞給一個(gè) prop 屬性的時(shí)候,它就變成了那個(gè)組件實(shí)例的一個(gè)屬性;為了給 Wiki 組件傳遞一個(gè)標(biāo)題,我們可以用一個(gè) props 選項(xiàng)將其包含在該組件可接受的 prop 列表中。
比如下面的例子:
Vue一個(gè)組件默認(rèn)可以擁有任意數(shù)量的 prop,任何值都可以傳遞給任何 prop;在上述模板中,我們能夠在組件實(shí)例中訪問(wèn)這個(gè)值,就像訪問(wèn) data 中的值一樣。
一個(gè) prop 被注冊(cè)之后,就可以像這樣把數(shù)據(jù)作為一個(gè)自定義屬性傳遞進(jìn)來(lái):
<當(dāng)然,在一個(gè)典型的應(yīng)用當(dāng)中,Wiki 是不可能僅僅有一個(gè)標(biāo)題的,那么我們可以把主體組織在 data 當(dāng)中,類(lèi)似于(為了簡(jiǎn)單就省略了主體內(nèi)容):
// 雖然我個(gè)人不建議,但是實(shí)際上不聲明對(duì)象而是注冊(cè)實(shí)例也是可行的同時(shí)為每一篇 Wiki 渲染一個(gè)獨(dú)立組件,包括編號(hào)、標(biāo)題和內(nèi)容等:
<如上所示,我們可以使用 v-bind 來(lái)動(dòng)態(tài)傳遞 prop,這在一開(kāi)始不清楚要渲染的具體內(nèi)容,比如從一個(gè) API 獲取文章列表的時(shí)候,是非常有用的,比如:
<!DOCTYPE html>上面的代碼當(dāng)中,從目標(biāo) API 地址獲取了一些文章內(nèi)容,并簡(jiǎn)單的使用 CSS 進(jìn)行了包裝,看起來(lái)文章之間的區(qū)別比較明顯了,并通過(guò)字體區(qū)分了標(biāo)題和內(nèi)容。
今天先到這里,之后的章節(jié)繼續(xù)深入組件,預(yù)計(jì)這個(gè)部分會(huì)比較長(zhǎng),我盡量堅(jiān)持每天一更,把這個(gè)部分通過(guò)我自己的理解講清楚它。不過(guò)再怎么樣,絕大部分內(nèi)容還是參照了官方文檔的,所以有些地方可能不夠清楚的,請(qǐng)留言告訴我,我再看看怎么改進(jìn)。
總結(jié)
以上是生活随笔為你收集整理的vue就地复用不是更快吗_Vue.js从零开始——组件(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: @cacheable 是否缓存成功_DN
- 下一篇: 检测电脑硬件的软件_为电脑DIY爱好者推