吐槽一下,掘金好像並不能插入gist的程式碼框 效果有點打折扣
部落格原文地址裡有gist程式碼:
使用Vue.js在WordPress中建立單頁面應用SPA
英文原文地址:premium.wpmudev.org/blog/creati…
在這篇文章裡,我將向你介紹如何使用Vue.js在WordPress中建立單頁面應用SPA(single page application):用WordPress做後端服務提供資料 ,用Vue.js獲取資料做前端渲染。
我們將用到WordPress的REST api (對外提供標準的RESTFul介面)和Vue.js (一個漸進式 JavaScript 框架)。如果你沒有用過Vue.js或者其他JavaScript框架,這會是一個很好的上手機會。
溫馨提示:本文面向有一定經驗的WordPress開發者,我假設你熟悉PHP, JavaScript和WordPress REST API。 如果你在這些方面是新手,推薦你先閱讀下面的教程:
- JavaScript for WordPress Developers
- A Quick Start Guide To The WordPress REST API
- JavaScript and the WordPress REST API: Understanding the Jargon
我們將會用到很多Vue.js的功能,比如單檔案元件,事件處理,計算屬性,生命週期,還會用到Axios庫和WordPress REST API進行互動。如果你不熟悉也沒關係,可以先學習下面的教程來快速上手:
雖然Vue.js應用完全可以用ES5語法來寫,但是我將用到一些ES6和ES7的新特性,如果你想快速學習一下ES6的語法,可以看看下面的教程:
- ES6 JavaScript – The Basics
- The WordPress Developer’s Guide To ES2015 (ES6)
- Five-minute crash course in ES6 & ES7
- ECMAScript 6 入門 – 阮一峰
選擇Vue.js或其他JavaScript框架主要看你自己的需求和技術偏好,本文的目標是用實際案例帶你探索一下把WordPress和前端單頁面應用結合起來的可能性。現在,讓我們開始吧!
概述:如何在WordPress中開發Vue單頁面應用
我已經在WordPress中利用Vue.js和Twenty Seventeen 主題的子主題(child theme)開發了一個簡單的帶搜尋功能的單頁面應用,程式碼共享在GitHub 上,你可以下載下來,一邊閱讀本文一邊檢視程式碼。
單頁面應用(SPA)可以掛載在任意一個Wordpress頁面(page)上,只要這個WordPress頁面指定了特定的自定義頁面模板(Custom Page Templates),這個自定義頁面模板的主要作用就是提供一個DOM元素,用作vue例項的掛載點。
我們的這個SPA採用的是一種混合架構,伺服器端的程式WordPress既為其提供後端服務,也為其提供前端渲染(如佈局和主題等),前端頁面的部分資料是通過瀏覽器端的應用(Vue.js)來渲染的。這和常見的SPA前後端分離架構不同,通常伺服器端程式僅負責提供內容(通過API響應),並不生成頁面內容的HTML。
使用Vue.js快速搜尋WordPress的日誌
在WordPress的搜尋場景中,每次搜尋都會對伺服器的發起一次請求,導致網頁重新載入。即使你只想簡單快速的搜尋一下WordPress的日誌標題也可能等半天(因為網路延時),這使WordPress的搜尋體驗變得很差。
SPA單頁面應用,只有一個完整的頁面,它在載入頁面時,不會載入整個頁面,而是隻更新某個指定的容器中內容。使用SPA,可以讓使用者在進行搜尋時動態更新網頁而不是重新載入。這使得使用者體驗非常愉悅。你可以通過的示例直觀感受一下
具備搜尋功能的Vue單頁面應用的元件剖析 {#vue-spa-overview}
在深入研究程式碼之前,讓我們瞭解一下這個單頁面應用的內部工作原理。下圖解釋了這個搜尋App中的元件互動流程。
讓我們總覽一下各個元件的作用:
AppNavigation
用於為Vue Router設定瀏覽器訪問路徑,並將AppQuickSearch
和AppCustomSearch
元件和路徑對映起來。- AppQuickSearch和AppCustomSearch是兩個完全相互獨立的父元件,每個元件都有各自的資料,方法和屬性,它們都有兩個子元件AppFilterSwitches和AppGetPosts。
AppFilterSwitches
用來控制核取方塊或按鈕的開關切換。AppGetPosts
會從WordPress REST API獲取資料,並通過關鍵字和過濾條件對結果進行過濾,然後呼叫AppDisplayPost元件來展示篩選結果。AppDisplayPost
裡定義了搜尋結果的展示樣式和HTML。
以上這些都是在WordPress的某個指定了自定義頁面模板的頁面中進行的。
使用Vue單檔案元件
你可能已經看到過許多使用Vue.component
方式來定義全域性元件的示例。在本文中,我將使用更強大的Vue單檔案元件。
單檔案元件具有許多優點,比如能提供預編譯的JavaScript ,完整語法高亮,CommonJS 模組以及元件作用域的CSS等。通過vue單檔案元件可以對前端專案進行模組化開發,並且使程式碼管理更清晰明瞭。
現在你已經對本文涉及的技術和原理有了一個大致的瞭解,接下來就讓我們開始開發吧。
使用Vue CLI設定本地開發工作環境
開發Vue單檔案元件將會需要使用一系列工具,如Vue Loader,Webpack,Babel等。但是,不要害怕,我會做一些必要的簡化,省略處理配置檔案的步驟。
使用Vue CLI 可以快速構建一個Vue應用程式。Vue CLI 是一個基於 Vue.js 進行快速開發的完整系統,它確保了各種構建工具能夠基於智慧的預設配置即可平穩銜接,這樣你可以專注在撰寫應用上,而不必花好幾天去糾結配置的問題。所以讓我們先設定一下Vue CLI 。
第1步:安裝Node.js.
要使用Vue CLI,你需要在系統上安裝Node.js(node版本大於8.x,npm版本大於3.x)。您可以從Node.js下載頁面下載適用於您的平臺的安裝程式。安裝完成後,請測試以下命令是否生效:
node --version
npm --version
第2步:安裝Vue-CLI
接下來,開啟系統的終端 ,執行npm install -g vue-cli
命令全域性安裝Vue-CLI(2.x)。完成後,執行vue --version
命令進行測試。
在上面的圖片中,你會發現,我還用npm install -g eslint全域性安裝了ESLint全域性範圍內與 。這是因為我使用Visual Studio Code和相關外掛來檢查JavaScript程式碼的規範化。你可以使用任何你喜愛的程式碼編輯器,但強烈建議你配置一個JavaScript的程式碼檢查工具,比如( ESLint, JSHint , StandardJS)。
完成基本設定後,讓我們使用Vue CLI在WordPress的主題資料夾中建立一個專案。
使用Vue CLI建立Vue專案
我使用了vue提供的官方模板webpack-simple 。當然,你可以根據你的需求使用更復雜的預設模板或者手動選擇。
Vue CLI使用Webpack來配置Vue專案,並提供了開發伺服器和其他現代構建工具。這為我們提供了非常便捷的開發流程。除此之外,它還允許我們在開發期間使用下一代JavaScript語法(ES6 / ES7)編寫程式碼,在釋出時編譯成對瀏覽器相容性更好的ES5語法的JavaScript包。
第1步:在WordPress中設定Vue應用程式
要建立一個vue專案,首先在終端進入到一個WordPress的主題目錄或子主題目錄(這個主題要在WordPress後臺啟用啟用)。
第2步:使用Webpack-Simple模板建立Vue應用程式
接下來,執行命令vue init webpack-simple project-name
,把project-name
替換成你的專案名字
(在我的示例中為spa),然後按照螢幕上的說明操作。這將在<project-name>
目錄中建立Vue專案,其中包含現代構建工具的配置。
注意:如果你下載使用我的vuetwentyseventeen子主題,請跳過vue init此步。資料夾中已經包含了spa
這個vue專案。
第3步:安裝開發依賴項
在新建立的專案資料夾中你會看到到一個名為package.json
的檔案。它基本上列出了所有專案所需的開發工具和依賴包。請執行以下命令來安裝這些所需的工具和庫:
cd spa
npm install
NPM將自動把所有依賴包下載並安裝到node_modules
的資料夾中。
請注意,不要在實際執行的線上WordPress中部署任何這些下載的依賴檔案。它們僅僅是在開發階段才需要。
第4步:在WordPress中啟動Webpack Dev Server
雖然看起來很奇怪,但你需要在執行WordPress本地服務(如XAMP,WAMP,VVV等)的同時,再執行在上一步中自動安裝的Webpack開發伺服器,使它們一同工作。
原因是這樣的,我們的單頁面應用實際上是獨立於後端的一個純靜態應用,在開發階段我們編寫的是vue單檔案元件,需要由Webpack伺服器來提供自動編譯和熱更新。只有在開發完成後,我們才能向WordPress提供最終編譯好的JavaScript包。
要啟動開發伺服器,請從Vue專案資料夾執行命令npm run dev
。然後,你將看到在瀏覽器中自動開啟localhost:8080
,也就是vue的初始化專案。
Vue.js的編譯打包
如果你在瀏覽器中檢視網頁原始碼,您會發現該頁面只包含一個JavaScript檔案 – build.js
。這是因為當你執行開發伺服器時,Webpack會自動編譯 ,使用不同的loaders處理專案的所有依賴檔案,最後打包為一個瀏覽器可識別的JavaScript檔案。
但請注意,該檔案實際上並沒有儲存在於您的系統上,而是由Node和Webpack在執行時動態生成的。
要生成可以釋出的JavaScript檔案,你必須執行npm run build
,我們將在稍後階段提到。
現在我們有了一個功能齊全的Vue應用,是由安裝在WordPress主題資料夾內的Webpack開發伺服器來提供服務的。但是,現階段除了物理安裝路徑它與WordPress沒有一毛錢關係。那麼,讓我們來看看如何將Vue應用與WordPress進行整合。
將Vue 與WordPress整合
將Vue應用與WordPress整合基本上需要三個條件:
- WordPress中的DOM元素,用做Vue例項的掛載點
- 在WordPress的排隊引用機制(Enqueue Scripts)中加入Vue的編譯檔案(如build.js)
- 在Vue中指定WordPress的DOM元素
在WordPress中為 Vue提供DOM元素
你可能希望將Vue例項掛在單個或多個WordPress頁面上,或者有條件地掛載。不管那種方式,Vue所需都是一個WordPress頁面上的DOM元素。
為此,你可以使用WordPress的Template Hierarchy(模板層次)來確定需要編輯哪個模板檔案。在我的示例中,我希望這個Vue SPA出現在任意一個指定了自定義頁面模板(Custom Page Template)的WordPress頁面上。你也可以使用主題的頁面模板來指定特定頁面,這取決於你的需求。
在我的示例子主題中,templates/vue-search-app-template.php
就是一個自定義頁面模板,它為Vue提供了DOM元素#wp-vue-app
。
在WordPress中註冊Vue應用程式
要讓WordPress能感知到Vue應用,你必須在WordPress中為Vue進行註冊/排隊 ( register/enqueue) 。因為在開發期間修改程式碼是很頻繁的,每次修改完vue程式碼之後都手動構建一次是很不方便的,為了方便,我們可以利用webpack的動態構建功能。
執行Webpack開發伺服器之後,我們就可以使用路徑http://localhost:8080/dist/build.js
在WordPress中註冊Vue例項。
vue程式碼修改儲存後,Webpack開發伺服器就會自動編譯並自動更新頁面 。
這就是為什麼在開發過程中我們必須同時執行WordPress的本地伺服器和Webpack開發伺服器的原因。開發完成後,你必須把路徑修改成通過npm run build
生成的檔案路徑。
另請注意,除了最終的編譯檔案之外,Vue專案資料夾中的所有檔案都不需要隨WordPress主題一起釋出。這些都僅在開發期間需要,並且每次修改後都必須進行重新編譯打包。
在我的示例主題中,我在includes/enqueue-scripts.php
註冊了Vue編譯後的檔案地址。
在Vue中指定WordPress中的DOM掛載點
最後,要在WordPress中載入Vue應用程式,所需的只是告訴Vue要掛載的位置。要在vue中指定WordPress DOM元素有兩種方法,你可以在main.js
使用el
,或者,也可以使用$mount
方法。
在我的示例中,我將vue應用掛載在自定義頁面模板的DIV容器#wp-vue-app
中。
就這樣,一個Vue初始專案將可以在WordPress中顯示了。
看起來不錯,Vue應用已經成功注入WordPress,你現在可以使用Vue構建幾乎任何你想要的東西。那麼,讓我們深入瞭解一下的用Vue來構建搜尋應用的內容。
在WordPress中構建單頁面搜尋應用
如果你再回頭看下 本文開頭的流程圖 ,您就能更好的理解下面的搜尋應用呈現的最終效果:
專案資料夾的結構
我用Vue示例專案作為基礎,從中刪除了spa/index.html
和src/assets
,得到了以下資料夾結構:
子主題的includes
資料夾裡的各個PHP檔案定義了相應的回撥函式,這樣我可以只使用一個functions.php
檔案來設定<a rel="noreferrer noopener" href="https://developer.wordpress.org/reference/hooks/" target="_blank">WordPress Hooks</a>
(鉤子函式)。我更喜歡這種方法將所有內容放在一個functions.php
檔案中。
安裝ESLint和ESNext功能(可選)
如果你打算使用ESLint(我強烈推薦)或ESNext功能(如Async / Await),你還需要為專案新增一些額外的依賴包。
為WordPress和Vue配置ESLint
為了配置ESLint,我安裝了eslint-plugin-vue和wodrdpress的程式碼規範eslint-config-wordpress。先停止開發伺服器(Ctrl + C),然後從Vue專案資料夾中執行以下命令:
npm install --save-dev eslint eslint-plugin-vue複製程式碼
npm install --save-dev eslint-config-wordpress複製程式碼
接下來,將以下內容新增到.eslintrc.json檔案中:
“extends”:[“eslint:recommended”,“wordpress”,“plugin:vue / recommended”]
這將為WordPress設定JavaScript程式碼規範 ,並設定vue官方推薦的eslint預設規則。配合VS Code這樣的程式碼編輯器,不僅可以很大程度地避免基本語法錯誤,也保證了程式碼的可讀性。
設定Babel以使用Async / Await
Babel設定超出了本文的範圍,用以下方法基本上可以讓你在Vue專案中使用ES7 的Async / Await語法。執行以下命令新增babel-preset-vue-app 即可:
npm install --save-dev babel-preset-vue-app
然後,在Vue專案中的.babelrc
檔案中新增預設(presets):
"presets": [["env", { "modules": false }], "stage-3", "vue-app"]
完成後,不要忘記使用npm run dev
啟動開發伺服器。我提供的示例子主題Vue child theme已經為你配置好了所有這些,因此你只需要通過在spa
目錄中執行npm install
來安裝即可。
從vue訪問WordPress資料
Vue是在瀏覽器中執行的JavaScript,因此,它無法訪問WordPress中的任何資料。要使WordPress資料可用於Vue應用程式,您必須使用wordpress的wp_localize_script 函式。
我在子主題vuetwentyseventeen
的includes/enqueue-scripts.php
中完成了這個配置。
上面gist裡的註釋已經很明瞭,所以我在這裡解釋一下需要提供給Vue應用程式的資料:
wpData.template_directory_uri
– 用來構建主題資料夾中靜態檔案的路徑wpData.rest_url
– 用來獲取WP資料的 REST API地址wpData.app_path
– 用於執行SPA的 WordPress頁面的URL地址wpData.post_categories
– wp的目錄,用於過濾條件的核取方塊
有了這些,我們終於可以開始開發vue單頁搜尋應用的單檔案元件了。
使用Vue單檔案元件構建單頁面搜尋應用
參照之前的元件架構,我開發的第一個元件是AppDisplayComponent
。讓我們將從最基本的功能開始,這個元件僅顯示帖子標題,使用的是JavaScript原生的Fetch API和WordPress的日誌資源Api (Posts resource – /wp/v2/posts
)。
AppDisplayPost元件的基本版本
接下來,我刪除了App.vue
裡原有的示例內容,並用下面的方式呼叫AppDisplayPost
元件用來在WordPress頁面上呈現日誌,如下所示:
當然,並不是所有東西都能一次成功,這就是Chrome外掛Vue DevTools發揮作用的時候了。我建議你也安裝一個,它可以使用友好的介面進行Vue應用的除錯和檢查,而不是用很土的辦法所有內容都輸出到瀏覽器控制檯。
我還建議你使用Postman之類的API工具與WP REST API進行互動。這可以節省你很多時間,並且資料展示也會更清晰,讓你更容易檢視API響應值:
第一次除錯在Vue應用中渲染WordPress日誌確實花了我一些時間,但利用Vue DevTools和Postman進行了幾輪嘗試之後就漸入佳境了,這讓我感覺不錯。我還決定對WordPRESS的API預設響應進行擴充套件以新增自定義內容。
擴充套件WordPress REST API的自定義內容
WordPress REST API的預設響應非常全面,但它很可能無法滿足你的所有需求。
例如,你可能希望顯示作者姓名,評論和日誌縮圖(特色影像)等資訊。如果你用Postman對日誌資源發起 GET請求 ,你會注意到這些資訊(作者、評論等)在預設響應中是不能直接使用的,需要根據響應裡得到的url發起二次請求。
當然,你可以通過一個簡單的方法來獲取更多資訊,將_embed=true引數新增到
wp/v2/posts地址後面再發起api請求 。使用
_embed,API將在響應中自動展開所有標記為embeddable: true
的欄位。
對於我的Vue 單頁搜尋應用程式,我決定擴充套件API的響應,並新增以下自定義內容:
如果你看一下我的子主題中AppDisplayPost
元件,你會注意到我使用到的欄位vue_meta
並不是API預設響應的內容。它是通過子主題中includes/extend-api.php檔案
的register_rest_field函式新增的,其中的程式碼非常簡單。如果你想要了解更多有關擴充套件API響應的知識,請檢視REST API Handbook的
Modifying Reponses`部分。
接下來,我建立了一個AppGetPosts
單檔案元件,把獲取日誌的程式碼邏輯移動到其中,AppDisplayPost
元件只用來顯示日誌。
AppGetPosts元件從REST API中獲取資料
把獲取日誌的程式碼分離出去,意味著要通過props將資料傳遞給AppDisplayPosts
元件 。
然後,在AppGetPosts
中我為獲取到的每篇日誌的呼叫了AppDisplayPost
元件。
我決定使用Axios而不是原生的Fetch API來請求WordPress REST API。你也可以選擇使用jQuery (已經包含在WordPress中)來進行AJAX呼叫。
注意:要使用Axios,你必須通過在Vue專案資料夾中執行npm install axios
進行生產環境下的安裝 。
用WordPress REST API獲取僅需欄位
我最近發現可以使用_fields引數從API響應中獲取僅需的欄位。這會有效減少api的網路傳輸負載,尤其是當api的JSON響應不出現的日誌內容時。要達到這個效果,只需將_fields
與逗號分隔的欄位名稱一起新增到api的url後面即可,如下圖
WordPress 的REST API手冊中還沒有加入_fields
引數的用法,因此你可能需要密切關注下手冊。
從WordPress REST API獲取所有帖子
目前,無法通過WordPress REST API一次性獲取所有日誌。所以,你必須向API迴圈發出多個請求,直到獲取到需要的所有資料為止。
我使用了分頁引數 per_page=100
和wordpress的http標頭欄位X-WP-Total
(提供了集合中的記錄總數)來計算總共要發起幾次API請求。per_page
引數目前上限為100條記錄,這就是為什麼我們需要在超過100個日誌時向API發出多個請求。實現方法請看下面的gist中AppGetPosts
元件的get_posts
函式:
上面的gist中, get_posts
函式會在元件掛載後自動呼叫. 我用了ES7 的Async/Await 寫法將該函式定義為非同步函式(aynchronous function )。
你會注意到第一個Axios
請求是await
的寫法-
const response = await axios(...)
。這是為了在第一次請求成功之前阻止後續程式碼的執行。這樣做是為了獲取x-wp-total
來計算的API請求次數。
第二個await用法是在最後,在渲染資料前用 Promise.all確保所有Promises都成功執行。當然,你也可以在資料載入完成後就渲染資料,兩種用法都在下面的gist裡列出了:
當所需資料載入完成後,我在計算屬性中新增了搜尋關鍵字和相應的搜尋邏輯。在下面的gist中,你可以看到我是如何用 FilteredResults
來過濾 wpPosts
資料並呼叫 AppDisplayPost
元件來顯示結果的。
AppQuickSearch和AppFilterSwitches元件
現在AppGetPosts
可以很好地工作了,能夠處理資料獲取和日誌搜尋,然後我將使用者輸入框移動到父元件AppQuickSearch
中,並使用props傳遞資料。
我建立了一個新的子元件AppFilterSwitches
用來顯示條件核取方塊(wp目錄列表,資料來源是WordPress的區域性物件 wpData
),這個子元件會觸發(emits)一個自定義事件onFilterToggle
,AppQuickSearch做為父元件必須去偵聽這個事件。
最後,所有元件都合併到AppQuickSearch
最後,執行npm run build
生成最終的編譯檔案。
如果你走到這一步了,你應該能很輕鬆的探索這個vue應用的其餘部分。最終版本的元件確實有很多,但它們建立在你剛看到的所有內容之上的。
探索路由和保持活動的元件
雖然我們的快速搜尋單頁應用到此就可以結束了,但是為了演示一下vue的路由機制(Vue routing)和元件的重複利用,我又新增了另一個元件AppCustomSearch
。
你可以在spa/src/app-routes.js
找到路由功能,它提供兩個導航連結AppQuickSearch
, AppCustomSearch
,並提供了導航連結和元件之間的對映關係。Vue Router的內容超出了本文的範圍,如果你想在WordPress頁面上使用Vue路由,請記住Vue將使用`#`來模擬一個完整的 URL,這樣當 URL 改變時,頁面不會重新載入。如果你嘗試去掉url裡的#直接訪問在app-routers.js裡定義的路由,那麼這個地址會被WordPress REST API接管,因為WordPress api裡並沒有這個地址,所以最終將找不到頁面並返回404。
App.vue
檔案是總元件,裡面呼叫了AppNavigation
和router-view元件。你會注意到router-view
被包keep-alive 元件中間, 這是因為使用_keep-alive_元件可以快取非活動元件,以便保留元件狀態,避免在AppQuickSearch
和AppCustomSearch
之間切換元件時重新渲染 。
就這些了!
總結
希望這篇文章對你有用。你可以在這裡下載這個子主題的檔案 ,當作一個練手專案來提高你的WordPress和JavaScript技能。
掘金好像不能插入gist,完整版的在這裡:使用Vue.js在WordPress中建立單頁面應用SPA