Vue有20樣寫法,你知道么?
當(dāng)前位置:點(diǎn)晴教程→知識管理交流
→『 技術(shù)文檔交流 』
引入打開 Vue3 的官方文檔,它首先會告訴你,Vue 的組件可以按兩種不同的風(fēng)格書寫:選項(xiàng)式 API 和組合式 API。文檔為我們提供一系列兩種風(fēng)格的代碼參考,供我們按照偏好進(jìn)行選擇。 實(shí)際上,Vue3 組件可不止兩種寫法,而是多達(dá)十幾種!然而,不管是什么寫法,它們都是基于同一個(gè)底層系統(tǒng)實(shí)現(xiàn)的,概念之間也是彼此相通的,只是使用的接口不同。在實(shí)際開發(fā)中,我們也不會同時(shí)使用到那么多種寫法,但是這并不意味著我們不需要去了解這些寫法! 如果你仔細(xì)閱讀 Vue3 的文檔,會發(fā)現(xiàn)一些示例或者 api 看起來模棱兩可,不知道這些 api 到底有什么用,或者閱讀 Vue 的源碼時(shí),總是能發(fā)現(xiàn)一些對于我們來說意圖不明的邏輯,那么,你可能先要了解一些 Vue 的寫法。先了解一個(gè)東西怎么用,再去分析它是怎么實(shí)現(xiàn)的。 看完本文章,你會收獲到:
本文章遵從循序漸進(jìn)的寫作順序,從易到難,輕松上手! setup 語法糖setup 語法糖應(yīng)該是最常用的寫法了。在 Vue3 中,我們想封裝一個(gè)組件,最習(xí)慣的做法還是新建一個(gè) Vue 文件,并將組件代碼寫在文件中。具體是:頁面結(jié)構(gòu)寫在 template 中,頁面邏輯寫在 script 中,頁面樣式寫在 style 中。 總之,我們將與該組件相關(guān)的代碼都寫在一起、放在一個(gè)文件中單獨(dú)維護(hù),在需要該組件的地方引入使用。 這里我們使用了 setup 語法糖,直接在 script 中書寫我們的 setup 內(nèi)部的邏輯。
在 App. vue 中引入并使用:
注:后續(xù)寫法盡管形式不同,但它們最終的目的都是導(dǎo)出一個(gè)組件,所以對于組件使用方來說(這里是 App. vue),怎么使用這個(gè)組件的代碼都是不變的,所以將不再重復(fù)此代碼。 Vue2 選項(xiàng)式寫法Vue2 經(jīng)典寫法這種寫法也是比較經(jīng)典的。和 setup 語法糖寫法類似。我們需要新建一個(gè) vue 文件來存儲我們的組件代碼,然后在需要使用該組件的地方對其進(jìn)行引入。區(qū)別在于,我們需要在 script 中導(dǎo)出一個(gè) Vue 實(shí)例。 這里我們導(dǎo)出的其實(shí)是一個(gè)普通對象,該對象包含 data、methods 等屬性。這個(gè)對象的屬性都是可選的,即 option,翻譯回來即“選項(xiàng)”。
defineComponent 輔助函數(shù)盡管我們在 script 語言塊中導(dǎo)出的默認(rèn)對象會被 vue 編譯器當(dāng)成 vue 實(shí)例,但不管怎么看,它依舊只是一個(gè) plain object。在定義組件實(shí)例方面,vue 提供了一個(gè)名為 defineComponent 輔助接口。
盡管這個(gè)接口也不能改變我們導(dǎo)出的是一個(gè)普通對象的事實(shí),但是它可以為我們的實(shí)例提供強(qiáng)大的類型推導(dǎo)。我們可以把它看成是一個(gè)返回 vue 實(shí)例的工廠函數(shù),讓我們的代碼看起來更加規(guī)范。 Vue3 選項(xiàng)式寫法在 Vue3 中,官方引入了新的選項(xiàng) setup,這是 Vue3 選項(xiàng)式寫法和 Vue2 寫法的主要區(qū)別。setup 選項(xiàng)的意義在于它允許我們在選項(xiàng)式的寫法中引用和使用組合式的 api,比如 onMounted、ref、reactive 等。但對于我們來說,它對于我們有益的地方還是基于它封裝起來的 setup 語法糖用起來很方便。
使用 defineComponent 時(shí),它能夠提示我們 setup 將會接收到什么參數(shù):
以上寫法我們都是在 template 上書寫我們的頁面結(jié)構(gòu),這也是最常見的幾種寫法,下面我們來介紹幾種了解 vue 底層必不可少的寫法,渲染函數(shù)。 手寫渲染函數(shù)template 模板語法本質(zhì)上也可以算是一種語法糖。在 vue 編譯器上,template 中的內(nèi)容最終會被翻譯為渲染函數(shù),掛載到 vue 實(shí)例的 render 屬性上。當(dāng)需要渲染組件時(shí),vue 就執(zhí)行一次 render,得到對應(yīng)的虛擬節(jié)點(diǎn)樹,最后再轉(zhuǎn)變?yōu)檎鎸?shí) dom。 Vue 允許我們脫離 template,直接自己書寫渲染函數(shù)。位置就在導(dǎo)出實(shí)例的 render 選項(xiàng)上:
在 template 中,我們使用類似 html 的模板語法來描述我們的視圖,在 render 函數(shù)中又如何描述呢?vue 提供了兩個(gè) api:createVnode 和 h。二者沒有區(qū)別,h 函數(shù)只是 createVnode 的縮寫。有了 render 函數(shù),我們就不需要寫 template 了。
在上面的示例中,我們使用 h 函數(shù)生成了一個(gè) vNode,并 return 出去,作為本組件最終在被使用時(shí)渲染出來的效果。 在 template 中我們可以使用 v-if、v-for、slot 等模板語法,在 h 函數(shù)中這些概念也是支持的,只是形式不同,這方面官方文檔有具體的示例??傊瑃emplate 模板和 render 選項(xiàng)是可以相互替代的。 setup 返回渲染函數(shù)setup 返回 render 方法一般來說,在選項(xiàng)式語法中,setup 方法返回一個(gè)對象,該對象暴露給 template,供 template 使用,具體參考第三個(gè)例子(vue3 選項(xiàng)式寫法)。如果我們不使用 template,也就沒有返回對象的必要了。 在 Vue3 中,還有另外一種不使用 template 的寫法,就是在 setup 方法中返回一個(gè) render 方法。
注意:
defineComponent 傳入setup就注意中的第一點(diǎn),我們可以采用下面這種寫法:直接在 defineComponent 中書寫 setup 函數(shù)(如果再省一點(diǎn)就是 setup 語法糖的寫法了)。
以上就是渲染函數(shù)的寫法,是不是有點(diǎn)感覺了呢,一下子就學(xué)會了兩個(gè) api!后面會提到的 Jsx 寫法其實(shí)也應(yīng)該歸為渲染函數(shù)寫法的一種(只要不是 template,而是用 JavaScript 表達(dá)頁面結(jié)構(gòu)的,都是渲染函數(shù)),但是相對于 h 函數(shù),jsx 并不是純粹的 js,所以我將它們分成了兩類。 Vue & Jsx在render 中使用 jsx有了前面兩類寫法介紹的鋪墊,接下來引入 jsx 語法就沒有什么難理解的點(diǎn)了。 jsx 在 vue 文件中是這樣寫的。在 render 渲染函數(shù)返回值處書寫 jsx 替代 h 函數(shù)。書寫純 JavaScript 的 h 函數(shù)描述結(jié)構(gòu)還是比較繁冗的,jsx 就是簡化了的h 函數(shù)寫法。
在 setup 中使用jsxjsx 和 setup 配合食用更加。在選項(xiàng)式風(fēng)格中使用 setup,在 setup 中使用組合式 api,并且返回 jsx 書寫的渲染函數(shù)。
defineComponent 簡寫這個(gè)其實(shí)就是前面介紹過的 「defineComponent 傳入 setup」 函數(shù)寫法:這里的區(qū)別只是使用 jsx 替代了 h 函數(shù)。
自行導(dǎo)出 vNode 對象我們也可以自己將 render 函數(shù)執(zhí)行一遍,然后將得到的 jsx Element 導(dǎo)出,和上一個(gè)示例「defineComponent 簡寫」是十分相似。但是這段代碼的缺點(diǎn)非常致命,它不支持接收外部傳遞來的屬性參數(shù)。
不要使用這種寫法。這里會提到這樣寫,只是因?yàn)楹秃竺娴?strong style="-webkit-tap-highlight-color: transparent;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important">「函數(shù)式組件(其二)」 寫法有關(guān)聯(lián)。本寫法與其它寫法都不同,其它寫法導(dǎo)出的都是 JavaScript 對象或者 jsx 對象,而這里我們則是自己執(zhí)行了一遍渲染函數(shù)并得到了虛擬節(jié)點(diǎn),直接將虛擬節(jié)點(diǎn)導(dǎo)出去。既然都已經(jīng)把虛擬節(jié)點(diǎn)創(chuàng)建出來了,那自然無法接收 props。 defineComponent 的第二個(gè)參數(shù)如果 defineComponent 的第一個(gè)參數(shù)是 setup 函數(shù),那么它的第二個(gè)參數(shù)則可以為組件的定義添加需要的選項(xiàng),但一般除了補(bǔ)充 props 選項(xiàng),不會再需要其它選項(xiàng)了(組合式 api 和 setup 的入?yún)⒖梢酝耆娲渌x項(xiàng))。
直接在 vue 中使用 jsx這里 jsx 不再只作為返回值,而是直接被某處使用。它可以是被直接導(dǎo)出,或者用在 template 上。 直接導(dǎo)出 jsx 對象直接將 jsx 對象導(dǎo)出使用。比前面的寫法更簡潔,做法就是把 setup 里面的內(nèi)容提到外面。這里需要注意的是我們導(dǎo)出的是一段直接的 jsx 對象(jsx Element),而不是渲染函數(shù)。
直接用在 template 上這種寫法可以幫助你在自身的組件內(nèi)復(fù)用一些顆粒度更小的組件,它和 setup 語法糖的寫法非常接近,只是 User 變量可以作為標(biāo)簽直接使用。
函數(shù)式組件(其一)你還可以將 User 寫成函數(shù)式組件,在本頁面內(nèi)使用。但它不會將連字符屬性轉(zhuǎn)換為小駝峰寫法。這和「直接用在 template 上」的內(nèi)容都是一樣的,它們都是為了方便在組件本身復(fù)用一些常用的組件。
如果你經(jīng)常使用 tailwind,你可能就會知道什么情況下會出現(xiàn)小顆粒度的可復(fù)用標(biāo)簽,比如,一個(gè)加了一大堆類名的 div 標(biāo)簽。 獨(dú)立的 Jsx 文件以上介紹的所有寫法,都是在 jsx 定義組件我們需要新建一個(gè) jsx/tsx 文件,然后只要保證導(dǎo)出的仍然是一個(gè)組件就可以了。有了前面的鋪墊,我們不難發(fā)現(xiàn),這不就是去掉 script 標(biāo)簽的選項(xiàng)式寫法嗎?確實(shí)!這是因?yàn)槲夜室庠谇懊姘才帕诉x項(xiàng)式寫法的例子,所以過渡到這里完全沒有壓力!
我還是推薦套上 defineComponent:
同樣地,前面對于 defineComponent 不同方式的使用這里也都可以的。比如導(dǎo)出普通對象并在 render 或者 setup 中使用 jsx 等等。從 vue 到 jsx,區(qū)別只是省下了 script 語法塊。 vue2 選項(xiàng)式寫法+jsx。
導(dǎo)出普通對象:
函數(shù)式組件(其二)Vue 中支持的最像函數(shù)式組件的寫法。
該例和前面的「自行導(dǎo)出 vNode 對象」非常接近,這也是為什么即使后者存在不能接收參數(shù)的缺陷我也會提出來,因?yàn)槎叨际鞘褂媒咏瘮?shù)式組件的寫法來描述組件的,但是在 vue 文件中并沒有辦法直接導(dǎo)出這個(gè)函數(shù)組件,而是需要自行執(zhí)行得到vNode。而在 jsx 文件中卻可以將其導(dǎo)出,并且支持接收參數(shù)。 如果你需要為其定義 props,也不需要使用 「defineComponent 的第二個(gè)參數(shù)」為你提供什么 props 選項(xiàng),而是直接在函數(shù)式組件的 props 、emits 屬性上掛載對應(yīng)的配置。
相信習(xí)慣了 React 的 fc 的小伙伴,看到這里一定感覺倍感親切。然而 Vue 的 Jsx 終究只是 Vue 的 Jsx,它并沒有像 React 一樣存在那么多強(qiáng)大的 Hooks 和內(nèi)置組件,而是僅僅只是 h 函數(shù)的便捷寫法。在語法上也和 React Jsx 存在諸多區(qū)別。和 React Jsx 相比,Vue Jsx 其實(shí)和自家的 template 更接近。不過 Vue Jsx 寫法的靈活性還是要比 template 模板高,但官方更推薦使用 template。template 更容易上手且提供了更好的性能優(yōu)化,除非你想完完全全掌控組件的每一個(gè)細(xì)節(jié),才需要jsx。 小結(jié)盡管本文提到了很多種寫法,但大多數(shù)寫法在大多數(shù)時(shí)候都是不會派上用場的,也應(yīng)該不被派上用場。之所以列舉那么多寫法,主要的目的還是為了循序漸進(jìn)引入 jsx 文件寫法和函數(shù)式組件寫法。 可以看出,Vue 的寫法本質(zhì)上是選項(xiàng)式的。Vue3 在 Vue2 的基礎(chǔ)上引入了 setup 選項(xiàng)和 setup 語法糖,結(jié)合組合式 api 后,開發(fā)者可以將組件的大部分邏輯都維護(hù)在 setup 中,而不是 vue2 中割裂了邏輯的 data+created+methods 選項(xiàng)。 在此基礎(chǔ)上,setup 語法糖支持自動導(dǎo)出組件功能,為我們?nèi)粘i_發(fā)帶來了很大的便利。 但是除了使用 template 來表達(dá)我們的結(jié)構(gòu),我們也可以自己使用 render 選項(xiàng)并借助 h 函數(shù)或者 jsx 的力量來手寫渲染函數(shù)。這些都是在 vue 文件中完成的。 既然都不需要 template 了,那么 vue 文件里就只剩下一個(gè) script 了(我們先忽略 style)。在 jsx 文件中,就允許我們直接書寫導(dǎo)出對象(仍是選項(xiàng)式的寫法),忽略script。 最后是 Vue 的 jsx 文件獨(dú)有的特性。它允許我們導(dǎo)出一個(gè)函數(shù)作為組件,我們稱之為函數(shù)式組件(fc,function component),這是 vue 文件和以前所有寫法所不具備的,外形與 React 相近。 總的來說就一句話,「Vue 本身仍然是選項(xiàng)式的,但是它現(xiàn)在還額外支持了在 jsx 文件中書寫 fc?!?/strong> 個(gè)人看法使用哪一種寫法,主要看個(gè)人偏好。每種寫法在特定場景下都有它的好處和壞處。選擇哪一種并不重要。但是我還是提幾點(diǎn)個(gè)人建議:
為什么不推薦函數(shù)式組件的寫法,因?yàn)樗枰獙懺?jsx 文件里。如果你只是想通過 jsx 為你的組件增強(qiáng)某些功能,直接改造 vue 文件更加方便,并且不需要修改你引入文件的后綴( 當(dāng)然以上只是我個(gè)人的小小看法。如果覺得有用,不妨動動小手點(diǎn)贊和收藏吧! 看到這里,如果你也想試試在 Vue 中寫 jsx,不妨看看這篇文章,分享了怎么在 Vue 項(xiàng)目中配置 jsx 環(huán)境,充分發(fā)揮 jsx 的優(yōu)勢! 傳送門:【Vue3】對el-form進(jìn)行二次封裝后,我的開發(fā)效率提升了3倍 - 掘金 參考渲染函數(shù) & JSX | Vue.js 該文章在 2024/10/19 12:27:24 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |