吐槽一下,掘金好像并不能插入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
所有评论(0)