
前言
很久没写博客了,今年转行做前端啦。Vue作为前端最火的三大框架之一,不玩儿到WordPress上怎么行呢?但Vue本身就是一个模板引擎,而WordPress作为文章发布系统,前台是需要被浏览器抓取的,要是前台使用模板引擎填充势必对搜索引擎不友好。所以就干脆在后台玩玩儿吧。于是尝试做了一下WordPress的主题设置选项页。传统的主题设置选项页做法已经很成熟并且有框架了,我这里就不再提了,下面简单介绍如何使用Vue这种前端技术来实现。
学习本文需有 Vue.js 的使用经验
技术栈
Vue 2.x – 前端数据绑定与模板引擎(至少需要IE9浏览器)
Element UI – 基于Vue的UI框架
WP REST API – 用于前端与后端的数据传输,WordPress4.7以上自带,老版本WP需插件
新增 REST API
由于我们需要做option的保存与读取,而WordPress并没有这个接口,因此我们需要手动写一个REST API接口用来保存和读取Option。因为vue对数据的保存是{name1:value1,name2:value2}的形式存储的,因此我们将api也写成这样的形式,方便数据提交。
此处需学习WordPress官方文档的REST API相关细节
在functions.php文件中新增下面的代码来手动增加API:
//使用REST API需要的一点点授权工作 wp_register_script( 'pf_restapi', '' ); $pf_api_translation_array = array( 'route' => esc_url_raw( rest_url() ), 'nonce' => wp_create_nonce( 'wp_rest' ), ); wp_localize_script( 'pf_restapi', 'pandastudio_framework', $pf_api_translation_array ); wp_enqueue_script( 'pf_restapi' ); //注册API地址 add_action( 'rest_api_init', function () { register_rest_route( 'vue', '/get_option/', array( 'methods' => 'post', 'callback' => 'get_option_by_RestAPI', )); register_rest_route( 'vue', '/update_option/', array( 'methods' => 'post', 'callback' => 'update_option_by_RestAPI', )); }); //读取Option function get_option_by_RestAPI( $data ) { $dataArray = json_decode($data->get_body(),true); $return = array(); foreach ($dataArray as $option_name => $value) { $return[$option_name] = get_option($option_name) ? get_option($option_name) : ""; } return $return; } //保存Option function update_option_by_RestAPI( $data ) { if (current_user_can('manage_options')) { $dataArray = json_decode($data->get_body(),true); foreach ($dataArray as $option_name => $value) { update_option($option_name,$value); } } }
新增页面
在functions.php中写增加后台设置页的代码
add_action('admin_menu', 'add_option_rest_page'); function add_option_rest_page(){ add_menu_page( '主题设置', '主题设置', 'manage_options', 'pf_options', 'create_Page', '', 60 ); }
此处需学习 add_menu_page 的使用方法,详见官方文档
接下来写创建页面的函数,由于我们要使用Vue和ElementUI来制作配置页面,因此需要先引入Vue和ElementUI。此处我们引入在线脚本作为示例
function create_Page () { ?> <script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-default/index.css"> <div id="vue_rest" class="wrap"> <!-- Vue模板:在这里编写Element-UI的代码 --> </div> <script type="text/javascript"> //Vue脚本:在这里编写Vue的对象 </script> <?php }
引入在线脚本会影响加载速度,强烈建议用于生产环境时使用主题本地的脚本和样式
写到这里本文就可以结束了(吃瓜群众:你逗我?!),下面只是使用Element UI和调用API的方法,任何一个前端开发者都应该能熟练上手
创建示例文本框
根据Element UI的开发文档,在上面“Vue模板”处做一个Element UI表单并增加两个输入框
<el-form ref="form" :model="form" label-width="100px"> <el-form-item label="第一个输入框"> <el-input v-model="sampleInput1"></el-input> </el-form-item> <el-form-item label="第二个输入框"> <el-input v-model="sampleInput2"></el-input> </el-form-item> </el-form>
然后在“Vue脚本”中新增一个Vue对象,绑定表单的输入框数据
var vue_rest = new Vue({ el: "#vue_rest", data() { return { sampleInput1 :"", sampleInput2 :"", } }, })
现在,打开后台设置页面,可以看到如下所示的界面了。我们所输入的字段都通过Vue绑定到了脚本的data里面
但是数据要怎么提交到后台呢?还需要一个保存按钮来使用一开始我们写好的API
制作保存按钮
根据Element UI的文档在刚才的表单后面做一个按钮,并绑定一个Vue method
<el-button type="primary" @click="save_config">保存</el-button>
在vue对象中新增这个method,然后用ajax去提交数据
methods: { save_config() { _this = this; jQuery.ajax({ url: pandastudio_framework.route + 'vue/update_option', type: 'POST', beforeSend: function ( xhr ) { xhr.setRequestHeader( 'X-WP-Nonce', pandastudio_framework.nonce ); }, data: JSON.stringify(_this._data), }) .done(function(data) { _this.$message.success('保存成功!') }) .fail(function() { _this.$notify.error({ title: '保存失败', message: '连接服务器失败或后台保存出错!' }); }) } }
效果如下
读取数据
我们发现,在进入页面的时候,数据仍然是空的,因此需要在vue被挂载的时候去读取一次数据,然后保存到data中。根据vue的生命周期文档,增加挂载时执行的脚本
mounted: function() { var _this = this; jQuery.ajax({ url: pandastudio_framework.route + 'vue/get_option', type: 'POST', beforeSend: function ( xhr ) { xhr.setRequestHeader( 'X-WP-Nonce', pandastudio_framework.nonce ); }, data: JSON.stringify(_this._data), }) .done(function(data) { for (var key in data) { _this[key] = data[key]; } }) .fail(function() { _this.loading = false; _this.show = false; _this.$alert('连接服务器失败或后台读取出错!', '数据读取失败', { confirmButtonText: '确定', }) }) }
至此,一个简单的后台页面读取和保存数据的功能就做好了。需要增加数据字段的时候,在Element UI的表单部分增加输入框,将值绑定到data就可以了。
在WordPress主题模板中读取存储字段的方法依旧是
<?php get_option("sampleInput1"); ?>
示例代码
在自带主题Twenty Seventeen中测试有效(粘贴到functions.php最末尾)
wp_register_script( 'pf_restapi', '' ); $pf_api_translation_array = array( 'route' => esc_url_raw( rest_url() ), 'nonce' => wp_create_nonce( 'wp_rest' ), ); wp_localize_script( 'pf_restapi', 'pandastudio_framework', $pf_api_translation_array ); wp_enqueue_script( 'pf_restapi' ); //新增API地址 add_action( 'rest_api_init', function () { register_rest_route( 'vue', '/get_option/', array( 'methods' => 'post', 'callback' => 'get_option_by_RestAPI', )); register_rest_route( 'vue', '/update_option/', array( 'methods' => 'post', 'callback' => 'update_option_by_RestAPI', )); }); //API方法 function get_option_by_RestAPI( $data ) { $dataArray = json_decode($data->get_body(),true); $return = array(); foreach ($dataArray as $option_name => $value) { $return[$option_name] = get_option($option_name) ? get_option($option_name) : ""; } return $return; } function update_option_by_RestAPI( $data ) { if (current_user_can('manage_options')) { $dataArray = json_decode($data->get_body(),true); foreach ($dataArray as $option_name => $value) { update_option($option_name,$value); } } } add_action('admin_menu', 'add_option_rest_page'); function add_option_rest_page(){ add_menu_page( '主题设置', '主题设置', 'manage_options', 'pf_options', 'create_Page', '', 60 ); } function create_Page () { ?> <script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-default/index.css"> <div id="vue_rest" class="wrap"> <!-- 在这里编写element-ui的代码 --> <el-form ref="form" :model="form" label-width="100px"> <el-form-item label="第一个输入框"> <el-input v-model="sampleInput1"></el-input> </el-form-item> <el-form-item label="第二个输入框"> <el-input v-model="sampleInput2"></el-input> </el-form-item> </el-form> <el-button type="primary" @click="save_config">保存</el-button> </div> <script type="text/javascript"> //在这里编写vue的对象 var vue_rest = new Vue({ el: "#vue_rest", data() { return { sampleInput1 :"", sampleInput2 :"", } }, mounted: function() { var _this = this; jQuery.ajax({ url: pandastudio_framework.route + 'vue/get_option', type: 'POST', beforeSend: function ( xhr ) { xhr.setRequestHeader( 'X-WP-Nonce', pandastudio_framework.nonce ); }, data: JSON.stringify(_this._data), }) .done(function(data) { for (var key in data) { _this[key] = data[key]; } }) .fail(function() { _this.loading = false; _this.show = false; _this.$alert('连接服务器失败或后台读取出错!', '数据读取失败', { confirmButtonText: '确定', }) }) }, methods: { save_config() { _this = this; jQuery.ajax({ url: pandastudio_framework.route + 'vue/update_option', type: 'POST', beforeSend: function ( xhr ) { xhr.setRequestHeader( 'X-WP-Nonce', pandastudio_framework.nonce ); }, data: JSON.stringify(_this._data), }) .done(function(data) { _this.$message.success('保存成功!') }) .fail(function() { _this.$notify.error({ title: '保存失败', message: '连接服务器失败或后台保存出错!' }); }) } } }) </script> <?php }
拓展
下面提供一些可以发散的思路,可以把这个设置页做得更好。代码较为复杂,不再示例,但都是基于本文实现的:
- 更多组件:本文只是简单描述了使用Vue、Element UI、Rest API来制作主题设置页的简单方法。利用前端技术完全可以扩展成更加复杂的表单,如:下拉菜单、单选框、色彩选择器、开关、slider滑动条等,甚至还可以在顶部加上Element UI做好的“Tab菜单”
- 导入导出:通过浏览器的生成Blob对象接口以及文件读取接口,还可以在无需增加后台PHP代码的前提下,完全用前端来实现option数据的导入导出
- 配色:Element UI的配色是浅蓝色,与WordPress不搭,可以用Element文档的 “在线主题生成工具” 生成适合WP的色彩主题
这是我最终做出来的效果,开开脑洞,可以做出更多功能
本文著作权归本人所有,未经许可谢绝转载!