承接上文,我们解决了PHP传递数据给JS的问题,现在,我们可以创建两个输入框和一个保存按钮。
- 输入框存储和修改选项值
- 保存按钮用于保存选项值
在页面加载的开始获取选项的值,将其作为输入框的默认值,修改输入框内容后点击保存按钮,将输入框的值通过 REST API 保存到 WordPress 中,并通过 get_option()
函数拿到对应的值。
流程介绍
详细流程如下
后端准备
在后端,我们要准备两个接口,分别是
- 读取选项接口,在页面的开始获取选项初始值
- 保存选项接口,点击保存按钮时保存选项
这两个接口会在后续的前端开发中用到。为了方便大家理解, 我们会从最简单的函数开始,然后逐步加大难度。
我们在 vue-spa 文件夹下新建 interface.php 文件,用来放置接口相关的代码。
填入以下代码,创建两个接口
//接口文件
function vuespa_create_api()
{
register_rest_route('pf/v1',
'/get_option/', array(
// 完整命名空间为:/wp-json/pf/v1/
'methods'
=>
'POST',
'callback'
=>
'get_option_by_RestAPI',
));
register_rest_route('pf/v1',
'/update_option/', array(
// 完整命名空间为:/wp-json/pf/v1/
'methods'
=>
'POST',
'callback'
=>
'update_option_by_RestAPI',
'permission_callback'
=>
function
()
{
return current_user_can('manage_options');
// 只有管理员才有权限修改
},
));
}
add_action('rest_api_init',
'vuespa_create_api');
读取选项接口
我们填入以下内容
//读取Option
//仅支持一对一的数据请求
function get_option_by_RestAPI($data)
{
//将传递数据转成数组类型
$dataArray = json_decode($data->get_body(),
true);
//新建数组
$return = array();
//循环获取对应选项ID的值,并将其存储在对应关联数组中,若拿不到值,则为空
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);
}
//返回成功信息
return
new WP_REST_Response(array(
'success'
=>
true,
'message'
=>
"已保存!"
),
200);
}
else
{
//返回失败信息
return
new WP_Error('save_error',
'保存失败!', array('status'
=>
500));
}
}
引入
现在,我们的 interface.php 文件准备好了,我们在 vue-spa.php 中添加以下代码引入该文件,
//接口
require_once plugin_dir_path(__FILE__)
.
'interface.php';
前端准备
我们需要用到 Vue3 和 Axios ,当然,只要能实现功能的,你喜欢的任何工具均可。
我们还需要在菜单页面中展示两个输入框和一个保存按钮
载入资源
修改 vue-spa.php
中的 vuespa_load_vues()
函数,我们需要引入 vue3 和 Axios 资源。改为以下代码
//载入所需 JS 和 CSS 资源 并传递数据
function vuespa_load_vues($hook)
{
//判断当前页面是否是指定页面,是则继续加载
if
('toplevel_page_vuespa_id'
!= $hook)
{
return;
}
//版本号
$ver =
'53';
//加载到页面顶部
wp_enqueue_style('vite', plugin_dir_url(__FILE__)
.
'vite/dist/index.css', array(), $ver,
false);
//加载到页面底部
wp_enqueue_script('vue',
'https://unpkg.com/vue@3/dist/vue.global.js', array(), $ver,
true);
wp_enqueue_script('axios',
'https://unpkg.com/axios/dist/axios.min.js', array(), $ver,
true);
wp_enqueue_script('vite', plugin_dir_url(__FILE__)
.
'vite/dist/index.js', array(), $ver,
true);
$pf_api_translation_array = array(
'route'
=> esc_url_raw(rest_url()),
//路由
'nonce'
=> wp_create_nonce('wp_rest'),
//验证标记
'data'
=> vuespa_data(),
//自定义数据
);
wp_localize_script('vite',
'dataLocal', $pf_api_translation_array);
//传给vite项目
}
//样式加载到后台
add_action('admin_enqueue_scripts',
'vuespa_load_vues');
在这里,为了让我们的 vue3 的 JS 文件能正确拿到文档节点,我们将 JS 的加载都从 false 改为 true ,这样,JS 就会加载到页面底部了。
现在,我们就能在菜单页面正常使用 vue3 的功能了。
准备输入框和按钮
我们修改 index.js 文件为以下代码
//vite/dist/index.js
const
App
=
{
setup()
{
//初始值
const datas =
Vue.reactive({
dataOne:
"",
dataTwo:
"",
});
//获取数据
const vuespa_get_option =
()
=>
{
axios
.post(dataLocal.route +
"pf/v1/get_option", datas,
{
headers:
{
"X-WP-Nonce": dataLocal.nonce,
"Content-Type":
"application/json",
},
})
.then((response)
=>
{
const data = response.data;
datas.dataOne = data.dataOne;
datas.dataTwo = data.dataTwo;
})
.catch((error)
=>
{
window.alert("连接服务器失败或后台读取出错!数据读取失败");
console.log(error);
});
};
//保存数据
const vuespa_update_option =
()
=>
{
axios
.post(dataLocal.route +
"pf/v1/update_option", datas,
{
headers:
{
"X-WP-Nonce": dataLocal.nonce,
},
})
.then((response)
=>
{
alert("保存成功");
})
.catch((error)
=>
{
alert("保存失败");
console.log(error);
});
};
//页面初始加载
Vue.onMounted(()
=>
{
console.log("简简单单");
vuespa_get_option();
});
return
{ datas, vuespa_update_option };
},
template:
'文本框1:<input type="text" v-model="datas.dataOne"><br/>文本框2:<input type="text" v-model="datas.dataTwo"><hr/><button class="button button-primary" @click="vuespa_update_option">保存</button>',
};
Vue.createApp(App).mount("#vuespa");
作用如下:
- 创建了一个响应式变量datas
- 创建了获取数据函数
vuespa_get_option()
通过上一节传来的网址进行拼接后发出post请求,并在标头中传入验证信息。 - 创建了保存数据函数
vuespa_update_option()
,与上述函数作用类似 - 我们在页面的开始,就加载
vuespa_get_option()
函数,将拿到的值作为输入框的默认值 - 我们通过 vue3 的模版,提供了两个 input输入框和一个按钮,
- input 的值与 datas 的变量进行双向绑定,按钮的点击事件绑定
vuespa_get_option()
函数进行数据保存
现在,刷新页面,就能看到我们创建的输入框,进行简单的修改,点击保存按钮,就能将数据保存到 WordPress 了。
wordpress 会缓存部分 JS 文件,建议您每次修改 JS 文件后,都修改函数
vuespa_load_vues()
中的版本号信息
原理浅析
当我们进入菜单页 VusSpa 时,观察控制台,会有一个get_option
的请求,内容如下
发出了请求,拿到了选项值,并将其作为默认值。
现在,我们修改输入框中的值,点击保存按钮,会触发update_option
,内容如下:
已将我修改的值传出了,并返回保存成功的信息。
调用
跟传统方法一样,我们使用get_option
来调用对应的选项值。
选项已准备好,我们开始调用,为了方便展示调用的数据,我们将选项值在菜单页中展示,
我们修改回调函数vuespa_menu_page_display()
,添加以下内容
echo "<h3>调用选项值</h3>";
echo get_option('dataOne');
echo "<br/>";
echo get_option('dataTwo');
可看到以下效果
问题
目前的功能是可以用了,但还有些问题
- 只能一对一的获取数据,在一些复杂场景中,这种数据结构很不友好
- 目前是手动载入 Vue3 和 Axios文件,加载缓慢,导致页面都加载好了,选项内容有些许延迟,有闪动感,体验不好
- 为了简单的功能,载入了 vue3 这个庞然大物,而且vue3的很多功能都没用上。
- 没有人员筛选、文章筛选和分类筛选之类的,与 WordPress 产生交互的功能,
针对以上问题,我们将在下一节中继续进行优化改进。