吐槽一下,掘金好像並不能插入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.js和Twenty Seventeen 主題的子主題(child theme)開發了一個簡單的帶搜索功能的單頁面應用,代碼共享在GitHub 上,你能夠下載下來,一邊閱讀本文一邊查看代碼。jquery
單頁面應用(SPA)能夠掛載在任意一個Wordpress頁面(page)上,只要這個WordPress頁面指定了特定的自定義頁面模板(Custom Page Templates),這個自定義頁面模板的主要做用就是提供一個DOM元素,用做vue實例的掛載點。
咱們的這個SPA採用的是一種混合架構,服務器端的程序WordPress既爲其提供後端服務,也爲其提供前端渲染(如佈局和主題等),前端頁面的部分數據是經過瀏覽器端的應用(Vue.js)來渲染的。這和常見的SPA先後端分離架構不一樣,一般服務器端程序僅負責提供內容(經過API響應),並不生成頁面內容的HTML。
在WordPress的搜索場景中,每次搜索都會對服務器的發起一次請求,致使網頁從新加載。即便你只想簡單快速的搜索一下WordPress的日誌標題也可能等半天(由於網絡延時),這使WordPress的搜索體驗變得不好。
SPA單頁面應用,只有一個完整的頁面,它在加載頁面時,不會加載整個頁面,而是隻更新某個指定的容器中內容。使用SPA,可讓用戶在進行搜索時動態更新網頁而不是從新加載。這使得用戶體驗很是愉悅。你能夠經過的示例直觀感覺一下
在深刻研究代碼以前,讓咱們瞭解一下這個單頁面應用的內部工做原理。下圖解釋了這個搜索App中的組件交互流程。
讓咱們總覽一下各個組件的做用:
AppNavigation
用於爲Vue Router設定瀏覽器訪問路徑,並將AppQuickSearch
和AppCustomSearch
組件和路徑映射起來。AppFilterSwitches
用來控制複選框或按鈕的開關切換。AppGetPosts
會從WordPress REST API獲取數據,並經過關鍵字和過濾條件對結果進行過濾,而後調用AppDisplayPost組件來展現篩選結果。AppDisplayPost
裏定義了搜索結果的展現樣式和HTML。以上這些都是在WordPress的某個指定了自定義頁面模板的頁面中進行的。
你可能已經看到過許多使用Vue.component
方式來定義全局組件的示例。在本文中,我將使用更強大的Vue單文件組件。
單文件組件具備許多優勢,好比能提供預編譯的JavaScript ,完整語法高亮,CommonJS 模塊以及組件做用域的CSS等。經過vue單文件組件能夠對前端項目進行模塊化開發,而且使代碼管理更清晰明瞭。
如今你已經對本文涉及的技術和原理有了一個大體的瞭解,接下來就讓咱們開始開發吧。
開發Vue單文件組件將會須要使用一系列工具,如Vue Loader,Webpack,Babel等。可是,不要懼怕,我會作一些必要的簡化,省略處理配置文件的步驟。
使用Vue CLI 能夠快速構建一個Vue應用程序。Vue CLI 是一個基於 Vue.js 進行快速開發的完整系統,它確保了各類構建工具可以基於智能的默認配置便可平穩銜接,這樣你能夠專一在撰寫應用上,而沒必要花好幾天去糾結配置的問題。因此讓咱們先設置一下Vue CLI 。
要使用Vue CLI,你須要在系統上安裝Node.js(node版本大於8.x,npm版本大於3.x)。您能夠從Node.js下載頁面下載適用於您的平臺的安裝程序。安裝完成後,請測試如下命令是否生效:
node --version
npm --version
接下來,打開系統的終端 ,運行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提供的官方模板webpack-simple 。固然,你能夠根據你的需求使用更復雜的預設模板或者手動選擇。
Vue CLI使用Webpack來配置Vue項目,並提供了開發服務器和其餘現代構建工具。這爲咱們提供了很是便捷的開發流程。除此以外,它還容許咱們在開發期間使用下一代JavaScript語法(ES6 / ES7)編寫代碼,在發佈時編譯成對瀏覽器兼容性更好的ES5語法的JavaScript包。
要建立一個vue項目,首先在終端進入到一個WordPress的主題目錄或子主題目錄(這個主題要在WordPress後臺激活啓用)。
接下來,運行命令vue init webpack-simple project-name
,把project-name
替換成你的項目名字
(在個人示例中爲spa),而後按照屏幕上的說明操做。這將在<project-name>
目錄中建立Vue項目,其中包含現代構建工具的配置。
注意:若是你下載使用個人vuetwentyseventeen子主題,請跳過vue init此步。文件夾中已經包含了spa
這個vue項目。
在新建立的項目文件夾中你會看到到一個名爲package.json
的文件。它基本上列出了全部項目所需的開發工具和依賴包。請運行如下命令來安裝這些所需的工具和庫:
cd spa
npm install
NPM將自動把全部依賴包下載並安裝到node_modules
的文件夾中。
請注意,不要在實際運行的線上WordPress中部署任何這些下載的依賴文件。它們僅僅是在開發階段才須要。
雖然看起來很奇怪,但你須要在運行WordPress本地服務(如XAMP,WAMP,VVV等)的同時,再運行在上一步中自動安裝的Webpack開發服務器,使它們一同工做。
緣由是這樣的,咱們的單頁面應用其實是獨立於後端的一個純靜態應用,在開發階段咱們編寫的是vue單文件組件,須要由Webpack服務器來提供自動編譯和熱更新。只有在開發完成後,咱們才能向WordPress提供最終編譯好的JavaScript包。
要啓動開發服務器,請從Vue項目文件夾運行命令npm run dev
。而後,你將看到在瀏覽器中自動打開localhost:8080
,也就是vue的初始化項目。
若是你在瀏覽器中查看網頁源代碼,您會發現該頁面只包含一個JavaScript文件 – build.js
。這是由於當你運行開發服務器時,Webpack會自動編譯 ,使用不一樣的loaders處理項目的全部依賴文件,最後打包爲一個瀏覽器可識別的JavaScript文件。
但請注意,該文件實際上並無保存在於您的系統上,而是由Node和Webpack在運行時動態生成的。
要生成能夠發佈的JavaScript文件,你必須運行npm run build
,咱們將在稍後階段提到。
如今咱們有了一個功能齊全的Vue應用,是由安裝在WordPress主題文件夾內的Webpack開發服務器來提供服務的。可是,現階段除了物理安裝路徑它與WordPress沒有一毛錢關係。那麼,讓咱們來看看如何將Vue應用與WordPress進行集成。
將Vue應用與WordPress集成基本上須要三個條件:
你可能但願將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進行註冊/排隊 ( 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編譯後的文件地址。
最後,要在WordPress中加載Vue應用程序,所需的只是告訴Vue要掛載的位置。要在vue中指定WordPress DOM元素有兩種方法,你能夠在main.js
使用el
,或者,也可使用$mount
方法。
在個人示例中,我將vue應用掛載在自定義頁面模板的DIV容器#wp-vue-app
中。
就這樣,一個Vue初始項目將能夠在WordPress中顯示了。
看起來不錯,Vue應用已經成功注入WordPress,你如今可使用Vue構建幾乎任何你想要的東西。那麼,讓咱們深刻了解一下的用Vue來構建搜索應用的內容。
若是你再回頭看下 本文開頭的流程圖 ,您就能更好的理解下面的搜索應用呈現的最終效果:
我用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功能(如Async / Await),你還須要爲項目添加一些額外的依賴包。
爲了配置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設置超出了本文的範圍,用如下方法基本上可讓你在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是在瀏覽器中運行的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單頁搜索應用的單文件組件了。
參照以前的組件架構,我開發的第一個組件是AppDisplayComponent
。讓咱們將從最基本的功能開始,這個組件僅顯示帖子標題,使用的是JavaScript原生的Fetch API和WordPress的日誌資源Api (Posts resource – /wp/v2/posts
)。
接下來,我刪除了App.vue
裏原有的示例內容,並用下面的方式調用AppDisplayPost
組件用來在WordPress頁面上呈現日誌,以下所示:
固然,並非全部東西都能一次成功,這就是Chrome插件Vue DevTools發揮做用的時候了。我建議你也安裝一個,它可使用友好的界面進行Vue應用的調試和檢查,而不是用很土的辦法全部內容都輸出到瀏覽器控制檯。
我還建議你使用Postman之類的API工具與WP REST API進行交互。這能夠節省你不少時間,而且數據展現也會更清晰,讓你更容易查看API響應值:
第一次調試在Vue應用中渲染WordPress日誌確實花了我一些時間,但利用Vue DevTools和Postman進行了幾輪嘗試以後就漸入佳境了,這讓我感受不錯。我還決定對WordPRESS的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
組件只用來顯示日誌。
把獲取日誌的代碼分離出去,意味着要經過props將數據傳遞給AppDisplayPosts
組件 。
而後,在AppGetPosts
中我爲獲取到的每篇日誌的調用了AppDisplayPost
組件。
我決定使用Axios而不是原生的Fetch API來請求WordPress REST API。你也能夠選擇使用jQuery (已經包含在WordPress中)來進行AJAX調用。
注意:要使用Axios,你必須經過在Vue項目文件夾中運行npm install axios
進行生產環境下的安裝 。
我最近發現可使用_fields參數從API響應中獲取僅需的字段。這會有效減小api的網絡傳輸負載,尤爲是當api的JSON響應不出現的日誌內容時。要達到這個效果,只需將_fields
與逗號分隔的字段名稱一塊兒添加到api的url後面便可,以下圖
WordPress 的REST API手冊中尚未加入_fields
參數的用法,所以你可能須要密切關注下手冊。
目前,沒法經過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
組件來顯示結果的。
如今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