如果你是一個 React 開發人員,並決定嘗試 Vue.js。歡迎參加這場聚會。
React 和 Vue 就像可口可樂和百事可樂,很多你可以在 React 中做的事,也同樣可以在 Vue 中做。不過兩者仍然有一些重要的概念上的差異,其中一些反映了 Angular 對 Vue 的影響。
接下來的文章中,我將重點討論下兩者的差異,以便你準備好切換到Vue,並且能馬上寫出高效的程式碼。
React 和 Vue 之間有多大的區別?
React 和 Vue 的相似性多於差異性:
- 都是用於建立 UI 的 JavaScript 庫
- 都是快速和輕量級的
- 都有基於元件的架構
- 都使用虛擬 DOM
- 都可以放在單獨的 HTML 檔案中,或者在更復雜的 Webpack 設定中的一個模組
- 都有獨立但常用的路由器和狀態管理庫
它們最大的區別在於 Vue 通常使用 HTML 模板檔案,而 React 是完全使用 JavaScript。Vue 還有具有可變狀態和稱為 “reactivity” 的重新渲染的自動系統。
我們將在下面一一道來。
Components
使用 Vue.js,元件將使用 API 方法 .component
進行宣告,該方法接收 id
和定義物件的引數。你可能會注意到 Vue 元件中熟悉的方面,以及不太熟悉的方面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
Vue.component('my-component', { // Props props: [ 'myprop' ], // Local state data() { return { firstName: 'John', lastName: 'Smith' } }, // Computed property computed: { fullName() { return this.firstName + ' ' + this.lastName; } }, // Template template: <div> <p>Vue components typically have string templates.</p> <p>Here's some local state: {{ firstName }}</p> <p>Here's a computed value: {{ fullName }}</p> <p>Here's a prop passed down from the parent: {{ myprop }}</p> </div> , // Lifecycle hook created() { setTimeout(() => { this.message = 'Goodbye World' }, 2000); } }); |
Template
你注意到元件有一個 template
屬性,它是一個 HTML 標記的字串。Vue 庫包括一個編譯器,它將在執行時將模板字串轉換為 render
函式。這些渲染由虛擬 DOM 實現。
你也可以選擇不使用模板,而用自定義 render
函式。你甚至可以使用 JSX。但是切換到 Vue 只是為了做這一點好像有點“作”。
生命週期
Vue 中的元件具有和 React 類似的生命週期方法。例如,當元件狀態準備就緒時,但在元件已經掛載(mounted)到頁面中之前,將會觸發 created
。
一個很大的區別:沒有 shouldComponentUpdate
。因為 Vue 的響應式系統(reactivity system)不需要它。
Re-rendering
Vue 初始化步驟之一是遍歷所有資料屬性並將其轉換為 getter
和 setter
。如果你看下面的內容,你可以看到 message
資料屬性如何新增一個 get
和 set
函式:
Vue 在訪問或修改屬性時新增了這些 getter 和 setter 來啟用依賴關係跟蹤和更改通知。
狀態管理
在 Vue 中改變一個元件的狀態,你不需要 setState
方法,只需要變異(mutate)。
1 2 3 4 5 |
// React this.setState({ message: 'Hello World' }); // Vue this.message = 'Hello World'; |
當 message
的值被變異(mutation)改變時,它將觸發 setter
。set
方法將設定一個新值,但也將執行一個輔助任務,通知 Vue 值已更改,依賴該頁面的任何部分可能需要重新渲染。
如果 message
作為一個 prop
傳遞給任何元件,Vue 知道它依賴於這個將自動重新渲染。這就是為什麼在 Vue 中不需要 shouldComponentUpdate
的原因。
主模板
關於主模板檔案,Vue 更像 Angular。與 React 一樣,Vue 需要掛載在頁面的某個位置。
1 2 3 |
<body> <div id="root"></div> </body> |
1 2 3 4 5 6 7 |
// React ReactDOM.render('...', document.getElementById('root')); // Vue new Vue({ el: '#root' }); |
不同於 React 的是,你可以繼續新增這個主 index.html
,因為它是根元件的模板。
1 2 3 4 |
<div id="root"> <div>You can add more markup to index.html</div> <my-component v-bind:myprop="myval"></my-component> </div> |
還可以通過使用 x-template
或 inline-template
等 HTML 功能來定義 index.html
中的子元件模板。儘管它將模板與元件定義的其餘部分分開,但這不被認為是最佳實踐。
指令(directives)
Vue 允許你通過指令邏輯來增強你的模板,再次同 Angular 一樣。這些特殊的 HTML 屬性擁有 v-
字首,例如,v-if
用於條件渲染,v-bind
用於將表示式繫結到常規 HTML 屬性。
1 2 3 4 5 6 7 |
new Vue({ el: '#app', data: { mybool: true, myval: 'Hello World' } }); |
1 2 3 4 |
<div id="app"> <div v-if="mybool">This renders if mybool is truthy.</div> <my-component v-bind:myprop="myval"></my-component> </div> |
分配給一個指令的值是一個 JavaScript 表示式,所以你可以參考資料屬性,包括三元運算子等。
工作流
儘管社群已經建立了create-vue-app
,但是 Vue 官方還沒有一個與 create-react-app
的等效物。
官方建議使用 vue-cli
初始化專案。它可以從一個簡單的專案生成一個 HTML 檔案,一個完整的 Webpack + 服務端渲染專案:
1 |
$ vue init template-name project-name |
單 HTML 檔案專案
Vue 作者尤雨溪將他的專案稱為“漸進式框架”,因為它可以擴充套件到複雜的應用程式,或縮小到簡單的應用程式。
當然了,React 也可以做到這一點。不同的是,Vue 專案通常使用較少的 ES6 功能,很少使用 JSX,所以通常不需要新增 Babel。此外,Vue 庫全部都在一個檔案中,沒有相應的 ReactDOM 的單獨檔案。
以下是將 Vue 新增到單個 HTML 檔案專案的方法:
1 |
<script src="https://unpkg.com/vue/dist/vue.js"></script> |
注意:如果你不打算使用模板字串,因此不需要模板編譯器,則會有一個較小的 Vue 構建,省略了這個稱為
vue.runtime.js
的檔案。大於 20KB。
單檔案元件
如果你樂意使用 Webpack 工具作為專案新增構建步驟,則可以使用 Vue 的單檔案元件(SFC)。這些檔案具有 .vue
副檔名,並將元件模板,JavaScript 配置和樣式全部封裝在一個檔案中:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<template> <div class="my-class">{{ message }}</div> </template> <script> export default { data() { message: 'Hello World' } } </script> <style> .my-class { font-weight: bold; } </style> |
這些毫無疑問是 Vue 最酷的功能之一。因為你使用 HTML 標記獲得“正確”的模板,但 JavaScript 正好在那裡,因此模板和邏輯之前沒有尷尬的分離。
有一個名為 vue-loader
的 Webpack 載入器負責處理 SFC。在構建過程中, 模板被轉換為一個渲染函式,因此這是瀏覽器中精簡版 vue.runtime.js
的完美用例。
Redux and more
Vue 還有一個名為 Vuex 的基於 Flux 的狀態管理庫。再次,它類似於 Redux,但有一些差異。
本文中我沒有時間介紹它,將在下週的文章中介紹。新增我的訂閱 來接收新的郵件訂閱。