告別jQuery,擁抱Vue.js:構建更簡潔高效的Web應用
想從零開始學習Vue.js?立即加入SitePoint Premium,獲取涵蓋Vue.js基礎知識、項目實戰、技巧工具及更多內容的完整Vue.js書籍合集,每月只需$14.99!
許多開發者在構建簡單應用時仍然依賴jQuery。雖然有時只需為頁面添加少量交互性,但使用JavaScript框架似乎顯得過於復雜——額外的代碼量、樣板代碼、構建工具和模塊打包器等等。從CDN引入jQuery似乎是輕而易舉的選擇。
本文旨在說服您,即使對於相對簡單的項目,使用Vue.js(以下簡稱Vue)也無需費力,反而能幫助您更快地編寫更好的代碼。我們將以一個簡單的示例為例,分別使用jQuery和Vue進行編碼,並逐步演示其差異。
本文將構建一個簡單的在線發票,使用Sparksuite提供的開源模板。希望這能比另一個待辦事項列表更有新意,並且具有足夠的複雜性來展示使用Vue的優勢,同時又易於理解。
我們將通過提供項目、單價和數量輸入來使其具有交互性,並在其中一個值更改時自動重新計算“價格”列。我們還將添加一個按鈕,用於在發票中插入新的空行,以及一個“總計”字段,該字段將在我們編輯數據時自動更新。
我已經修改了模板,以便單個(空)行的HTML如下所示:
<tr> class="item"> <td><input type="text" v-model="item.description" /></td> <td><input type="number" v-model="item.price" /></td> <td><input type="number" v-model="item.quantity" /></td> <td><pre class="brush:php;toolbar:false"><code class="language-javascript">$('table').on('mouseup keyup', 'input[type=number]', calculateTotals);
首先,讓我們看看如何使用jQuery來實現這個功能。
function calculateTotals() { const subtotals = $('.item').map((idx, val) => calculateSubtotal(val)).get(); const total = subtotals.reduce((a, v) => a + Number(v), 0); $('.total td:eq(1)').text(formatAsCurrency(total)); }
我們將監聽器附加到表格本身,當“單位成本”或“數量”值更改時,將執行calculateTotals函數:
function calculateSubtotal(row) { const $row = $(row); const inputs = $row.find('input'); const subtotal = inputs[1].value * inputs[2].value; $row.find('td:last').text(formatAsCurrency(subtotal)); return subtotal; }
此函數查找表格中的所有項目行並循環遍歷它們,將每一行傳遞給calculateSubtotal函數,然後將結果相加。然後,將此總計插入到發票的相關位置。
<tr> class="item"> <td><input type="text" v-model="item.description" /></td> <td><input type="number" v-model="item.price" /></td> <td><input type="number" v-model="item.quantity" /></td> <td><pre class="brush:php;toolbar:false"><code class="language-javascript">$('table').on('mouseup keyup', 'input[type=number]', calculateTotals);
在上面的代碼中,我們獲取對行中所有輸入元素的引用,並將第二個和第三個相乘以獲得小計。然後,將此值插入到行中的最後一個單元格中。
function calculateTotals() { const subtotals = $('.item').map((idx, val) => calculateSubtotal(val)).get(); const total = subtotals.reduce((a, v) => a + Number(v), 0); $('.total td:eq(1)').text(formatAsCurrency(total)); }
我們還有一個輔助函數,用於確保小計和總計都格式化為兩位小數,並在前面加上貨幣符號。
function calculateSubtotal(row) { const $row = $(row); const inputs = $row.find('input'); const subtotal = inputs[1].value * inputs[2].value; $row.find('td:last').text(formatAsCurrency(subtotal)); return subtotal; }
最後,我們有一個“添加行”按鈕的點擊處理程序。我們在這裡所做的是選擇最後一個項目行並創建一個副本。克隆行的輸入設置為默認值,並將其插入為新的最後一行。我們還可以為用戶提供便利,並將焦點設置到第一個輸入,以便他們可以開始鍵入。
以下是完整的jQuery演示:CodePen鏈接
jQuery的缺點
那麼,這段代碼有什麼問題呢?或者說,什麼地方可以改進?
您可能聽說過Vue和React等一些較新的庫聲稱是聲明式的而不是命令式的。當然,查看這段jQuery代碼,大部分代碼都是關於如何操作DOM的指令列表。每一部分代碼的目的——“是什麼”——往往很難通過“怎麼做”的細節來分辨出來。當然,我們可以通過將其分解成命名良好的函數來闡明代碼的意圖,但這段代碼仍然需要一些努力才能在一段時間後重新理解。
此類代碼的另一個問題是,我們將應用程序狀態保存在DOM本身中。訂購項目的相關信息僅作為構成UI的HTML的一部分存在。當我們只在一個位置顯示信息時,這似乎不是什麼大問題,但是一旦我們開始需要在應用程序中的多個位置顯示相同的數據,確保每個部分保持同步就會變得越來越複雜。沒有單一的事實來源。
雖然沒有什麼可以阻止我們不將狀態保存在DOM之外並避免這些問題,但像Vue這樣的庫提供了促進創建良好架構和編寫更簡潔、更模塊化代碼的功能和結構。
那麼,我們如何使用Vue來重現此功能呢?
正如我前面提到的,Vue不需要我們使用模塊打包器、轉譯器或選擇單文件組件(.vue文件)來開始使用。像jQuery一樣,我們可以簡單地從CDN包含庫。讓我們從替換script標籤開始:
function formatAsCurrency(amount) { return `$${Number(amount).toFixed(2)}`; }
接下來,我們需要創建一個新的Vue實例:
$('.btn-add-row').on('click', () => { const $lastRow = $('.item:last'); const $newRow = $lastRow.clone(); $newRow.find('input').val(''); $newRow.find('td:last').text('<pre class="brush:php;toolbar:false"><code class="language-html"><🎜>
這裡我們只需要提供el選項,它是一個選擇器(就像我們使用jQuery一樣),用於標識我們想要Vue管理的文檔的哪個部分。
我們可以讓Vue負責從整個頁面(例如,對於單頁應用程序)或單個
數據
讓我們還將三個示例行的相關數據添加到我們的Vue實例中:
<tr> class="item"> <td><input type="text" v-model="item.description" /></td> <td><input type="number" v-model="item.price" /></td> <td><input type="number" v-model="item.quantity" /></td> <td><pre class="brush:php;toolbar:false"><code class="language-javascript">$('table').on('mouseup keyup', 'input[type=number]', calculateTotals);
data屬性是我們在其中存儲應用程序狀態的地方。這不僅包括我們希望應用程序使用的任何數據,還包括有關UI狀態的信息(例如,選項卡組中當前活動的部分,或者手風琴是展開還是折疊)。
Vue鼓勵我們將應用程序的狀態與它的表示(即DOM)分開,並集中在一個地方——單一的事實來源。
修改模板
現在讓我們設置我們的模板來顯示來自我們data對像中的項目。因為我們已經告訴Vue我們希望它控製表格,所以我們可以在HTML中使用它的模板語法來告訴Vue如何渲染和操作它。
使用v-for屬性,我們可以為items數組中的每個項目渲染一段HTML:
function calculateTotals() { const subtotals = $('.item').map((idx, val) => calculateSubtotal(val)).get(); const total = subtotals.reduce((a, v) => a + Number(v), 0); $('.total td:eq(1)').text(formatAsCurrency(total)); }
Vue將為我們傳遞給v-for構造的數組(或對象)的每個元素重複此標記,允許我們在循環中引用每個元素——在本例中為item。由於Vue正在觀察data對象的所有屬性,因此它將隨著items內容的變化而動態地重新渲染標記。我們只需向應用程序狀態添加或刪除項目,Vue就會負責更新UI。
我們還需要添加輸入框,以便用戶填寫項目的描述、單價和數量:
function calculateSubtotal(row) { const $row = $(row); const inputs = $row.find('input'); const subtotal = inputs[1].value * inputs[2].value; $row.find('td:last').text(formatAsCurrency(subtotal)); return subtotal; }
在這裡,我們使用v-model屬性來設置輸入和項目模型上的屬性之間的雙向綁定。這意味著對輸入的任何更改都將更新項目模型上的相應屬性,反之亦然。
在最後一個單元格中,我們使用雙大括號{{ }}來輸出一些文本。我們可以在大括號內使用任何有效的JavaScript表達式,因此我們將兩個項目屬性相乘並輸出結果。同樣,由於Vue正在觀察我們的數據模型,因此對任一屬性的更改都將導致表達式自動重新計算。
事件和方法
現在我們已經設置好模板來渲染我們的items集合,但是我們如何添加新行呢?由於Vue將渲染items中的任何內容,因此要渲染空行,我們只需要將具有我們想要的任何默認值的對象推送到items數組中即可。
要創建可以在模板中訪問的函數,我們需要將它們作為methods對象的屬性傳遞給我們的Vue實例:
function formatAsCurrency(amount) { return `$${Number(amount).toFixed(2)}`; }
讓我們定義一個addRow方法,我們可以調用它來向我們的items數組添加新項目:
$('.btn-add-row').on('click', () => { const $lastRow = $('.item:last'); const $newRow = $lastRow.clone(); $newRow.find('input').val(''); $newRow.find('td:last').text('<pre class="brush:php;toolbar:false"><code class="language-html"><🎜>
請注意,我們創建的任何方法都會自動綁定到Vue實例本身,因此我們可以訪問data對像中的屬性和其他方法,作為this的屬性。
那麼,現在我們有了方法,如何在點擊“添加行”按鈕時調用它呢?在模板中向元素添加事件監聽器的語法是v-on:event-name:
const app = new Vue({ el: 'table' });
Vue還為我們提供了一個快捷方式,以便我們可以使用@代替v-on:,就像我在上面的代碼中所做的那樣。對於處理程序,我們可以指定Vue實例中的任何方法。
計算屬性
現在我們只需要在發票底部顯示總計即可。我們可能可以在模板本身中做到這一點:正如我前面提到的,Vue允許我們在花括號之間放置任何JavaScript語句。但是,最好將任何超過非常基本的邏輯的內容都保留在模板之外;如果我們將邏輯分開,則更清晰且更容易測試。
我們可以為此使用另一個方法,但我認為計算屬性更合適。與創建方法類似,我們將一個包含函數的computed對像傳遞給我們的Vue實例,我們希望在模板中使用這些函數的結果:
<tr> class="item"> <td><input type="text" v-model="item.description" /></td> <td><input type="number" v-model="item.price" /></td> <td><input type="number" v-model="item.quantity" /></td> <td><pre class="brush:php;toolbar:false"><code class="language-javascript">$('table').on('mouseup keyup', 'input[type=number]', calculateTotals);
現在我們可以在模板中引用此計算屬性:
function calculateTotals() { const subtotals = $('.item').map((idx, val) => calculateSubtotal(val)).get(); const total = subtotals.reduce((a, v) => a + Number(v), 0); $('.total td:eq(1)').text(formatAsCurrency(total)); }
正如您可能已經註意到的那樣,計算屬性可以像數據一樣對待;我們不必用括號調用它們。但是使用計算屬性還有另一個好處:Vue足夠聰明,可以緩存返回值,並且只有當它依賴的數據屬性之一發生更改時,才會重新計算該函數。
如果我們使用方法來計算總計,則每次重新渲染模板時都會執行計算。因為我們使用的是計算屬性,所以只有在項目的數量或價格字段發生更改時才會重新計算總計。
過濾器
您可能已經發現我們的實現中存在一個小錯誤。雖然單位成本是整數,但我們的總計和小計顯示時沒有顯示美分。我們真正想要的是始終將這些數字顯示為兩位小數。
與其修改計算小計和計算總計的代碼,Vue為我們提供了一種處理此類常見格式化任務的好方法:過濾器。
正如您可能已經猜到的那樣,要創建過濾器,我們只需將具有該鍵的對像傳遞給我們的Vue實例:
function calculateSubtotal(row) { const $row = $(row); const inputs = $row.find('input'); const subtotal = inputs[1].value * inputs[2].value; $row.find('td:last').text(formatAsCurrency(subtotal)); return subtotal; }
在這裡,我們創建了一個非常簡單的名為currency的過濾器,它調用value.toFixed(2)並返回結果。我們可以將其應用於模板中的任何輸出,如下所示:
function formatAsCurrency(amount) { return `$${Number(amount).toFixed(2)}`; }
以下是完整的Vue演示:CodePen鏈接
將兩個版本的代碼並排比較,Vue應用程序的幾個方面很突出:
兩個庫的大小(以KB為單位)幾乎相同。當然,您可以通過自定義構建來精簡jQuery,但是即使對於像我們的發票示例這樣的相對簡單的項目,我認為開發的便捷性和代碼的可讀性也證明了這種差異是合理的。
Vue還可以做很多我們在這裡沒有介紹的事情。它的優勢在於允許您創建模塊化、可重用的UI組件,這些組件可以組合成複雜的frontend應用程序。如果您有興趣深入了解Vue,我建議您查看《Getting Up and Running with the Vue.js 2.0 Framework》。
jQuery是一個快速、小巧且功能豐富的JavaScript庫。它使HTML文檔遍歷和操作、事件處理和動畫等操作更加簡單,它易於使用的API可在多種瀏覽器中運行。另一方面,Vue.js是一個用於構建用戶界面的漸進式JavaScript框架。與其他整體框架不同,Vue的設計從一開始就具有增量可採用性。核心庫僅關注視圖層,易於上手並與其他庫或現有項目集成。
雖然jQuery多年來一直是一個可靠的工具,但Vue.js提供了一種更現代、更全面的構建Web應用程序的方法。 Vue.js是基於組件的,這促進了可重用性和可維護性。它還有一個更強大的生態系統,具有狀態管理、路由等工具。此外,Vue.js具有虛擬DOM,在某些情況下可以提高性能。
將jQuery代碼轉換為Vue.js需要了解jQuery函數的等效Vue.js方法和屬性。例如,您將使用Vue的mounted()生命週期鉤子來代替jQuery的$(document).ready()。類似地,您將使用Vue的axios或fetch來代替jQuery的$.ajax()來進行HTTP請求。
雖然從技術上講可以同時使用jQuery和Vue.js,但通常不建議這樣做。混合使用兩者可能會導致代碼混亂和潛在衝突,因為這兩個庫都試圖以自己的方式管理DOM。最好完全使用其中一個。
在jQuery中,您通常使用.click()、.on()或.bind()等方法將事件監聽器附加到元素。在Vue.js中,您使用v-on指令(或其簡寫@)來監聽DOM事件並在觸發時運行一些JavaScript。
jQuery沒有內置的數據綁定。您手動選擇元素並更新其內容。相反,Vue.js具有強大的數據綁定係統。您可以使用v-model指令在表單輸入、textarea和select元素上創建雙向數據綁定。
jQuery具有內置的動畫方法,如.fadeIn()、.slideUp()等。另一方面,Vue.js提供轉換組件,在將元素動畫進出DOM時允許更大的靈活性。
在jQuery中,您通常使用$.ajax()方法發出HTTP請求。 Vue.js沒有內置的此方法,但是您可以使用現代API(如fetch)或axios等庫來發出HTTP請求。
jQuery沒有內置的反應性系統。當您的數據更改時,您會手動更新DOM。另一方面,Vue.js具有反應性數據系統。當您更改數據時,視圖會自動更新。
許多jQuery插件都可以用Vue.js組件替換。 Vue.js擁有豐富的生態系統,提供了數千個可用的開源組件。您還可以創建自己的自定義組件。這提高了代碼的可重用性和可維護性。
請注意,我已根據您的要求對輸出進行了改寫,並保留了所有圖片的原始格式和位置。 由於我沒有訪問CodePen,我無法提供實際的CodePen鏈接,請您自行創建並替換“[CodePen鏈接]”佔位符。
以上是如何用vue替換jQuery的詳細內容。更多資訊請關注PHP中文網其他相關文章!