如何構建你的第一個 Vue.js 元件

發表於2018-01-29

如何構建你的第一個 Vue.js 元件

記得當那天使用 CakePHP 開發的時候,我很喜歡它簡易入門的特性。其文件不僅結構嚴密,詳盡,而且對使用者友好。多年以後,我在 Vue.js 上找到了同樣的感覺。然而,與 Cake 相比,Vue 文件還有一個缺點:(缺乏)真實的專案教程。

不管框架的文件有多好,對與所有人來說都是不夠的。閱讀有關的概念並不是總能幫助你瞭解更多東西,也不能幫助你理解如何使用它們來實際做出某些事情。如果你和我一樣,你會在實踐過程中學到更多,在你編碼的時候參考文件,因為你需要它們。

在本教程中,我們將構建一個星級評分系統元件。我們將在需要時介紹幾個 Vue.js 概念,並介紹為什麼要使用它們。

TL;DR: 這篇文章詳細的介紹瞭如何使用 vue.js 和為什麼使用 vue.js 。它旨在幫助掌握 Vue.js 的一些核心概念,並教你如何為未來的專案做出設計決策。如果你想了解整個思維過程,請繼續閱讀。否則,你可以直接檢視 CodeSandbox 上的最終程式碼。

入門指南

Vue.js(正確地)以一個簡單的指令碼引入足以開始執行,但是當你想使用single-file components,情況會有所不同。 現在,你不必這樣構建元件。 你可以很容易地用 Vue.component 定義一個全域性元件。

問題在於,這樣做需要權衡使用字串模板,沒有 CSS 支援,也沒有構建步驟(所以沒有前處理器)。 然而,我們想要更深入地學習如何構建一個真正的在專案中使用的實際元件。出於這些原因,我們將使用由 Webpack 提供支援的實際設定。

為了保持簡單並減少配置時間,我們將使用 vue-cli 和簡單的 webpack-simple Vue.js模板。

首先,你需要全域性安裝 vue-cli。啟動你的終端並鍵入以下內容:

你現在可以通過幾個按鍵生成隨時可用的 Vue.js 樣板。然後繼續輸入:

你會碰到幾個問題。 選擇除“使用sass”之外的所有預設值,你應該回答 yes(y)。然後,vue-cli 將初始化專案並建立 package.json 檔案。完成後,可以導航到專案目錄,安裝依賴關係,然後執行專案:

就這麼簡單!Webpack 將開始在埠 8080(如果可用)上為你的專案提供服務並在瀏覽器中啟動它。如果一切順利,你應該看到這樣的歡迎頁面。

如何構建你的第一個 Vue.js 元件

我們做到了嗎?

可以說我們做到了!為了正確除錯你的Vue.js元件,你需要正確的工具。 繼續並安裝Vue.js devtools瀏覽器擴充套件(Firefox/Chrome/Safari)。

你的第一個元件

Vue.js最好的功能之一是single-file components(SFC)。 它們允許您在一個檔案中定義元件的結構,樣式和行為,而不存在混合HTML,CSS和JavaScript的常見缺陷。

SFC以.vue副檔名結尾,並具有以下結構:

讓我們開始建立我們的第一個元件:在/src/components中建立一個Rating.vue檔案,然後複製/貼上上面的程式碼片段。然後,開啟/src/main.js並調整現有的程式碼:

 

最後,新增一些HTML程式碼到你的Rating.vue檔案:

現在看看你的瀏覽器中的頁面,你應該看到列表。Vue.js會將您的元件附加到index.html中的#app元素。如果檢查HTML,則應該看不到#app元素的符號:Vue.js將其替換為元件。

旁註:你有沒有注意到你甚至不需要重新載入頁面?這是因為Webpack的vue-loader帶有一個熱載入功能。與實時重新載入或瀏覽器同步相反,每次更改檔案時,熱重新載入都不會重新整理頁面。而是監視元件更改,只重新整理它們,保持狀態不變。

現在,我們已經花了一些時間來設定,是時候真正寫出有意義的程式碼了。

模板

我們將使用 vue-awesome,一個用 Font Awesome icons 構建的 Vue.js 的 SVG 圖示元件。我們可以只載入我們需要的圖示,使用 npm(或 Yarn)進行安裝:

 

然後編輯你的元件,如下所示:

好吧,讓我們慢一點,解釋一下。

Vue.js 使用原生 ES6 模組來處理依賴和匯出元件。

圖示是一個 Vue.js SFC,就像我們正在構建的這一個。如果你開啟這個檔案,你會發現它和我們的結構完全一樣。

export default 模組將物件文字匯出為我們元件的檢視模型。我們在元件屬性中註冊了 Icon 元件,所以我們可以在本地使用它。

最後,我們在 HTML 中使用了 Icon,並傳遞了一個 name 屬性來定義我們想要的圖示。通過將元件轉換為 kebab-case(例如:MyComponent 變成 ),可以將元件用作自定義 HTML 標記。我們不需要在元件內嵌入任何東西,所以我們使用了一個自閉合標籤。

旁註:你有沒有注意到我們在 HTML 中新增了一個

標籤?這是因為我們還在根級別的中新增了一個計數器,Vue.js 中的元件模板只接受一個根元素。如果你不遵守,會得到一個編譯錯誤。
樣式如果你已經使用過 CSS,你應該知道一個主要的挑戰就是要處理它的全域性性。巢狀一直被認為是解決這個問題的方法。但現在我們知道它很快就會導致特殊性問題,使得樣式難以覆蓋,不能被重用,並且這將是一個難以衡量的噩夢。於是發明了像 BEM 這樣的方法來繞過這個問題,並且通過名稱空間類來保持低的特異性。有一段時間,這是編寫乾淨和可擴充套件的 CSS 的理想方法。然後,像 Vue.js 或 React 這樣的框架和庫就出現了,並將 scoped styling 引入表中。React 具有樣式化的元件,Vue.js 具有 scoped styling CSS。它可以讓你編寫特定元件的 CSS,而不必拿出一些技巧來保持它的包含結構。您使用“普通”類名編寫常規 CSS,Vue.js 通過將資料屬性分配給 HTML 元素並將其附加到編譯樣式來處理範圍限定。

讓我們在元件上新增一些簡單的類:

和 css 樣式:

看到那個scoped屬性了嗎? 這是告訴 Vue.js 去範圍化樣式,所以他們作用範圍不會涵蓋到其他地方。 如果您在 index.html 中正確地複製/貼上 HTML 程式碼,您將注意到您的樣式不適用:這是因為它們的作用域是元件。

那麼前處理器呢?

Vue.js 使得從簡單的 CSS 切換到您最喜歡的前處理器變得輕而易舉。你所需要的只是適當的 Webpack 載入器和

現在我們可以使用 Sass 編寫元件級樣式,匯入變數,顏色定義或混合等部分。如果您更喜歡縮排語法(或“sass”符號),只需在 lang 屬性中將 scss 切換 sass 即可。

行為

現在我們的元件看起來不錯,現在是時候讓它開始工作了。目前,我們有一個硬編碼的模板。讓我們設定一些初始的模擬狀態,並調整模板,使其顯示出來:

我們在這裡所做的是使用 Vue 的資料來設定元件狀態。你在 data 中定義的每個屬性都是有響應性的:如果它發生變化,它將反映在檢視中。

我們正在建立一個可重用的元件,因此 data 需要成為工廠函式而不是物件文字。這樣我們就得到了一個新的物件,而不是一個可以跨幾個元件共享的現有物件。

我們的 data 工廠返回兩個屬性:stars,當前“活動”的 star 數和 maxStars,還有一個就是元件中 star 的總數。因為我們會適配我們的模板規則,所以它反映了元件的實際狀態。Vue.js 帶有一堆指令,可以讓您將演示邏輯新增到模板中,而無需將其與純 JavaScript 程式碼混合。v-fordirective 遍歷任何可迭代的物件(陣列,物件文字,對映等)。它也可以把一個數字作為一個範圍重複 x 次、這就是我們用 v-for=”star in maxStars” 所做的,所以我們對元件中的每個星星都有一個<li>。
您可能已經注意到一些屬性以冒號為字首,這是 v-bind 指令的縮寫,它將屬性動態繫結到表示式。我們可以把它寫成長的形式,v-bind:class。當 star 處於活動狀態時,我們需要在<li>元素上新增 active 類。在我們的專案下,這意味著每個<li>的索引小於 stars 應該有 active 類。我們在 :class 指令中使用了一個表示式,噹噹前 star 小於總 star 數時,才會追加 active。同樣條件下我們使用三元運算子來定義 Icon 元件使用的什麼樣的圖示:star 或 star-o。那計數器呢?現在我們的 star 列表是繫結到實際的資料,現在我們是時候對計數器也執行相同的操作。最簡單的方法是使用帶有 mustache 語法的文字插值:

很簡單,不是嗎? 現在在這種況下,這是訣竅。 但是,如果我們需要一個更復雜的 JavaScript 表示式,最好將其抽象到一個計算屬性中。

在這裡,這是矯枉過正。 我們可以避開模板內表示式,並保持可讀性。然而,當你不得不處理更復雜的邏輯時,記住計算的屬性。

另一件我們需要做的是提供一種方法來隱藏計數器,如果我們不需要它的時候。 最簡單的方法是使用帶有布林值的 v-if 指令。

互動

我們差不多完成了,但是我們仍然需要實現元件中最有趣的部分:響應性。我們將使用 v-on,這是處理事件和方法的 Vue.js 指令,可以附加所有方法的 Vue.js 屬性

我們在<li>上新增了 @click 屬性,這是 v-on:click 的簡寫。該指令包含對我們在元件的 methods 屬性中定義的 rate 方法的呼叫。
“等一下…這看起來非常像熟悉的 HTML 的 onclick 屬性。在 HTML 中使用內聯 JavaScript 不是一個過時和不好的做法嗎?“確實如此,但是即使語法看起來很像 onclick,但比較兩者是一個錯誤。當你構建一個 Vue.js 元件時,你不應該把它看作是分離的 HTML/CSS/JS,而應該是一個使用多種語言的元件。當專案在瀏覽器中開啟服務或編譯生產時,所有的 HTML 和指令都被編譯成普通的 JavaScript。如果您檢查已渲染的 HTML,您將看不到您的指令的任何標誌,也沒有任何 onclick 屬性。Vue.js 會編譯好你的元件並建立合適的繫結。

這也是為什麼您可以從模板訪問元件的上下文的原因:因為指令繫結到檢視模型。與具有單獨 HTML 的傳統專案相反,模板是元件的組成部分。

回到我們的 rate 方法。我們需要將 stars 變為 clicked 元素的索引,所以我們通過 @click 指令的索引,可以做到以下幾點:

去檢視您的瀏覽器頁面,並嘗試點選 star:它執行成功了

如果你開啟瀏覽器開發者工具欄中的 Vue 皮膚並選擇 元件,當你點選 star 時,你會看到資料的變化。這表明你的 star 屬性是響應性的:當你改變它的時候,它會把它的改變指派給檢視。 這個概念被稱為資料繫結,如果您使用過 Backbone.js 或 Knockout 之類的框架,您應該熟悉這個概念。 不同之處在於,Vue.js 和 React 一樣,只能在一個方向上進行:這就是所謂的單向資料繫結。不過這個話題值得寫一篇單獨的文章。

在這一點上,我們可以認為已完成 —— 但我們可以做更多的工作來改善使用者體驗。

現在,我們實際上不能給出 0 的等級,因為點選一個 star 會將它的比率設定為它的索引。更好的方案是重新點選同一顆 star,並切換至其當前狀態,而不是保持 active 狀態。

現在,如果點選的 star 的索引等於 star 當前值,我們就減少它的值。 否則,我們給它分配 star 值。

如果我們想要徹底解決,我們還應該新增一個控制層,以確保 star 從來沒有被賦予一個沒有意義的值。我們需要確保 star 永遠不會小於 0,也絕不會比 maxStars 更大,而且它是一個合適的數字。

傳遞 props 屬性

現在,元件的資料在資料屬性中被硬編碼。如果我們希望我們的元件實際上是可用的,我們需要能夠從其例項傳遞自定義資料。在 Vue.js 中,我們用 props 做到這一點。

和在 main.js 檔案裡:

這裡有三件事要注意:

首先,我們使用 v-bind 簡寫從元件例項傳遞 props 屬性:這就是 Vue.js 所謂的動態語法。當你想要傳遞一個字串值時,你不需要知道它的具體值,為此,字面值語法(沒有 v-bind 的普通屬性)將起作用。但對我們而言,由於我們正在傳遞數字和布林值,所以這很重要。

props 和資料屬性在編譯時被合併,所以我們不需要改變在檢視模型或模板中呼叫屬性的方式。出於同樣的原因,我們不能在 props 資料屬性中使用相同的名稱。

最後,我們定義了一個級別屬性,並將其作為 star 數值屬性中的值傳遞給它。我們之所以這樣做,不是直接使用級別屬性,而是因為級別改變,值會發生變化。在 Vue.js 中,props 從父級傳遞給子級,而不是反過來傳遞,所以你不會改變父級的狀態。這將違背 單向資料流 的原則,使事情難以除錯。這就是為什麼你不應該試圖改變子元件內的 prop。相反,定義一個使用 props 的初始值作為自聲的本地資料屬性。

最後的潤色

在這一天馬上過去之前,我們應該瞭解 Vue.js 最後一個驚奇的地方:prop 的驗證。

Vue.js 允許你在傳遞給元件之前控制 prop。您可以執行四個主要的事情:檢查型別,要求定義一個 prop 屬性,設定預設值,並執行自定義驗證

我們使用型別檢查來確保將正確型別的資料傳遞給元件。這將對我們忘記使用動態語法來傳遞非字串值的錯誤特別有用。我們也確保通過要求它填寫 grade 屬性。對於其他 props 屬性,我們定義了預設值,所以即使沒有傳遞自定義資料,元件也能正常工作。

現在我們可以簡單地通過執行以下操作來例項化元件:

就是這樣!您剛剛建立了第一個 Vue.js 元件,並探索了許多概念,包括使用 vue-clisingle-file components 生成樣板程式,匯入元件, scoped styling, directives, event handlers, computed properties, custom methods, one-way data flow, propsprop validation。這都是 Vue.js 所提供的表層特性!

這是一個非常詳細的教程,所以碰到不明白的地方,建議再次閱讀,在部分章節之間暫停和探索和,並嘗試擺弄下 CodeSandbox 上的原始碼

相關文章