使用Vue.js在WordPress中建立單頁面應用SPA

吐槽一下,掘金好像並不能插入gist的代碼框 效果有點打折扣javascript

博客原文地址裏有gist代碼: 使用Vue.js在WordPress中建立單頁面應用SPAphp

英文原文地址:premium.wpmudev.org/blog/creati…css


在這篇文章裏,我將向你介紹如何使用Vue.js在WordPress中建立單頁面應用SPA(single page application):用WordPress作後端服務提供數據 ,用Vue.js獲取數據作前端渲染。html

咱們將用到WordPress的REST api (對外提供標準的RESTFul接口)和Vue.js (一個漸進式 JavaScript 框架)。若是你沒有用過Vue.js或者其餘JavaScript框架,這會是一個很好的上手機會。前端

舒適提示:本文面向有必定經驗的WordPress開發者,我假設你熟悉PHP, JavaScript和WordPress REST API。 若是你在這些方面是新手,推薦你先閱讀下面的教程:vue

咱們將會用到不少Vue.js的功能,好比單文件組件事件處理計算屬性,生命週期,還會用到Axios庫和WordPress REST API進行交互。若是你不熟悉也不要緊,能夠先學習下面的教程來快速上手:html5

雖然Vue.js應用徹底能夠用ES5語法來寫,可是我將用到一些ES6和ES7的新特性,若是你想快速學習一下ES6的語法,能夠看看下面的教程:java

選擇Vue.js或其餘JavaScript框架主要看你本身的需求和技術偏好,本文的目標是用實際案例帶你探索一下把WordPress和前端單頁面應用結合起來的可能性。如今,讓咱們開始吧!node

概述:如何在WordPress中開發Vue單頁面應用

我已經在WordPress中利用Vue.js和Twenty Seventeen 主題的子主題(child theme)開發了一個簡單的帶搜索功能的單頁面應用,代碼共享在GitHub 上,你能夠下載下來,一邊閱讀本文一邊查看代碼。jquery

單頁面應用(SPA)能夠掛載在任意一個Wordpress頁面(page)上,只要這個WordPress頁面指定了特定的自定義頁面模板(Custom Page Templates),這個自定義頁面模板的主要做用就是提供一個DOM元素,用做vue實例的掛載點。

Integrating a Vue app in WordPress
用自定義頁面模板將Vue.js與 WordPress 結合起來

咱們的這個SPA採用的是一種混合架構,服務器端的程序WordPress既爲其提供後端服務,也爲其提供前端渲染(如佈局和主題等),前端頁面的部分數據是經過瀏覽器端的應用(Vue.js)來渲染的。這和常見的SPA先後端分離架構不一樣,一般服務器端程序僅負責提供內容(經過API響應),並不生成頁面內容的HTML。

使用Vue.js快速搜索WordPress的日誌

在WordPress的搜索場景中,每次搜索都會對服務器的發起一次請求,致使網頁從新加載。即便你只想簡單快速的搜索一下WordPress的日誌標題也可能等半天(由於網絡延時),這使WordPress的搜索體驗變得不好。

SPA單頁面應用,只有一個完整的頁面,它在加載頁面時,不會加載整個頁面,而是隻更新某個指定的容器中內容。使用SPA,可讓用戶在進行搜索時動態更新網頁而不是從新加載。這使得用戶體驗很是愉悅。你能夠經過的示例直觀感覺一下

codepen.io/karannagupt…

具有搜索功能的Vue單頁面應用的組件剖析 {#vue-spa-overview}

在深刻研究代碼以前,讓咱們瞭解一下這個單頁面應用的內部工做原理。下圖解釋了這個搜索App中的組件交互流程。

vue搜索spa內部結構
Vue單頁面搜索應用的內部邏輯

讓咱們總覽一下各個組件的做用:

  • AppNavigation用於爲Vue Router設定瀏覽器訪問路徑,並將AppQuickSearchAppCustomSearch組件和路徑映射起來。
  • 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命令進行測試。

設置vue cli 2
設置Vue-CLI(2.x)以建立Vue應用程序

在上面的圖片中,你會發現,我還用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後臺激活啓用)。

導航到wordpress主題
進入到WordPress主題目錄

第2步:使用Webpack-Simple模板建立Vue應用程序

接下來,運行命令vue init webpack-simple project-name ,把project-name 替換成你的項目名字 (在個人示例中爲spa),而後按照屏幕上的說明操做。這將在<project-name>目錄中建立Vue項目,其中包含現代構建工具的配置。

注意:若是你下載使用個人vuetwentyseventeen子主題,請跳過vue init此步。文件夾中已經包含了spa這個vue項目。

使用vue init和webpack模板的vue應用程序
使用vue init和Webpack模板建立Vue應用程序

第3步:安裝開發依賴項

在新建立的項目文件夾中你會看到到一個名爲package.json的文件。它基本上列出了全部項目所需的開發工具和依賴包。請運行如下命令來安裝這些所需的工具和庫:

cd spa
npm install

NPM將自動把全部依賴包下載並安裝到node_modules的文件夾中。

安裝dev依賴項
使用NPM安裝開發依賴項

請注意,不要在實際運行的線上WordPress中部署任何這些下載的依賴文件。它們僅僅是在開發階段才須要。

第4步:在WordPress中啓動Webpack Dev Server

雖然看起來很奇怪,但你須要在運行WordPress本地服務(如XAMP,WAMP,VVV等)的同時,再運行在上一步中自動安裝的Webpack開發服務器,使它們一同工做。

緣由是這樣的,咱們的單頁面應用其實是獨立於後端的一個純靜態應用,在開發階段咱們編寫的是vue單文件組件,須要由Webpack服務器來提供自動編譯和熱更新。只有在開發完成後,咱們才能向WordPress提供最終編譯好的JavaScript包。

要啓動開發服務器,請從Vue項目文件夾運行命令npm run dev 。而後,你將看到在瀏覽器中自動打開localhost:8080,也就是vue的初始化項目。

運行webpack開發服務器
運行Webpack開發服務器

Vue.js的編譯打包

若是你在瀏覽器中查看網頁源代碼,您會發現該頁面只包含一個JavaScript文件 – build.js 。這是由於當你運行開發服務器時,Webpack會自動編譯 ,使用不一樣的loaders處理項目的全部依賴文件,最後打包爲一個瀏覽器可識別的JavaScript文件。

但請注意,該文件實際上並無保存在於您的系統上,而是由Node和Webpack在運行時動態生成的。

在內存中由webpack生成的javascript包
由Webpack在運行時動態生成的JavaScript包

要生成能夠發佈的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中註冊動態構建路徑

這就是爲何在開發過程當中咱們必須同時運行WordPress的本地服務器和Webpack開發服務器的緣由。開發完成後,你必須把路徑修改爲經過npm run build生成的文件路徑。

在開發腳本以後註冊構建
在開發以後在WordPress中註冊實際的構建文件

另請注意,除了最終的編譯文件以外,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中指定安裝點
使用’el’在Vue中指定掛載點

就這樣,一個Vue初始項目將能夠在WordPress中顯示了。

在wordpress中注入vue
在WordPress中渲染Vue應用程序

看起來不錯,Vue應用已經成功注入WordPress,你如今可使用Vue構建幾乎任何你想要的東西。那麼,讓咱們深刻了解一下的用Vue來構建搜索應用的內容。

在WordPress中構建單頁面搜索應用

若是你再回頭看下 本文開頭流程圖 ,您就能更好的理解下面的搜索應用呈現的最終效果:

vue搜索應用程序wordpress
在WordPress中構建Vue搜索應用程序

項目文件夾的結構

我用Vue示例項目做爲基礎,從中刪除了spa/index.htmlsrc/assets ,獲得瞭如下文件夾結構:

wordpress中的vue文件夾結構
WordPress中Vue搜索應用程序的文件夾結構

子主題的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這樣的代碼編輯器,不只能夠很大程度地避免基本語法錯誤,也保證了代碼的可讀性。

爲vue wordpress配置eslint
在Visual Studio代碼中使用ESLint捕獲錯誤

設置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 函數。

我在子主題vuetwentyseventeenincludes/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組件的基本版本

入門的基本組件
AppDisplayPost組件的簡單版本

接下來,我刪除了App.vue裏原有的示例內容,並用下面的方式調用AppDisplayPost組件用來在WordPress頁面上呈現日誌,以下所示:

app.vue組件的初始版本
App.vue來裏的AppDisplayPost組件

固然,並非全部東西都能一次成功,這就是Chrome插件Vue DevTools發揮做用的時候了。我建議你也安裝一個,它可使用友好的界面進行Vue應用的調試和檢查,而不是用很土的辦法全部內容都輸出到瀏覽器控制檯。

使用vue devtools進行調試
使用Vue Devtools調試Vue應用

我還建議你使用Postman之類的API工具與WP REST API進行交互。這能夠節省你不少時間,而且數據展現也會更清晰,讓你更容易查看API響應值:

休息客戶郵遞員與wordpress休息api互動
使用Postman之類的REST客戶端與WordPress REST 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的響應,並添加如下自定義內容:

延伸wordpress rest api
擴展WordPress REST API的默認響應

若是你看一下個人子主題中AppDisplayPost組件,你會注意到我使用到的字段vue_meta並非API默認響應的內容。它是經過子主題中includes/extend-api.php文件register_rest_field函數添加的,其中的代碼很是簡單。若是你想要了解更多有關擴展API響應的知識,請查看REST API HandbookModifying 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後面便可,以下圖

檢索特定字段休息api
使用_fields參數有選擇地獲取api響應中的字段

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生成最終的編譯文件。

生成最終應用構建
使用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文件是總組件,裏面調用了AppNavigationrouter-view組件。你會注意到router-view被包keep-alive 組件中間, 這是由於使用_keep-alive_組件能夠緩存非活動組件,以便保留組件狀態,避免在AppQuickSearchAppCustomSearch之間切換組件時從新渲染 。

就這些了!

總結

但願這篇文章對你有用。你能夠在這裏下載這個子主題的文件 ,看成一個練手項目來提升你的WordPress和JavaScript技能。


掘金好像不能插入gist,完整版的在這裏:使用Vue.js在WordPress中建立單頁面應用SPA

原文地址:premium.wpmudev.org/blog/creati…

相關文章
相關標籤/搜索