第二节:Vue3 开发WordPress设置选项- 从输入框开始,配置基础设置选项

本节中,我们实现了两个输入框进行获取和修改选项,并通过保存按钮将选项的值保存进 WordPress 中。本节代码较多,但注释详细,做好准备咯

承接上文,我们解决了PHP传递数据给JS的问题,现在,我们可以创建两个输入框和一个保存按钮。

  • 输入框存储和修改选项值
  • 保存按钮用于保存选项值

在页面加载的开始获取选项的值,将其作为输入框的默认值,修改输入框内容后点击保存按钮,将输入框的值通过 REST API 保存到 WordPress 中,并通过 get_option() 函数拿到对应的值。

流程介绍

详细流程如下

第二节:Vue3 开发WordPress设置选项- 从输入框开始,配置基础设置选项

后端准备

在后端,我们要准备两个接口,分别是

  • 读取选项接口,在页面的开始获取选项初始值
  • 保存选项接口,点击保存按钮时保存选项

这两个接口会在后续的前端开发中用到。为了方便大家理解, 我们会从最简单的函数开始,然后逐步加大难度。

我们在 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的请求,内容如下

第二节:Vue3 开发WordPress设置选项- 从输入框开始,配置基础设置选项

发出了请求,拿到了选项值,并将其作为默认值。

现在,我们修改输入框中的值,点击保存按钮,会触发update_option,内容如下:

第二节:Vue3 开发WordPress设置选项- 从输入框开始,配置基础设置选项


已将我修改的值传出了,并返回保存成功的信息。

调用

跟传统方法一样,我们使用get_option来调用对应的选项值。

选项已准备好,我们开始调用,为了方便展示调用的数据,我们将选项值在菜单页中展示,
我们修改回调函数vuespa_menu_page_display(),添加以下内容

    echo "<h3>调用选项值</h3>";
    echo get_option('dataOne');
    echo "<br/>";
    echo get_option('dataTwo');

可看到以下效果

第二节:Vue3 开发WordPress设置选项- 从输入框开始,配置基础设置选项

完整代码

vue-spa.php

<?php
/*
Plugin Name: Vue - SPA 
Plugin URI: https://www.npc.ink
Description: 将vue构建的页面嵌入WordPress 中并产生交互
Author: Muze
Author URI: https://www.npc.ink
Version: 1.0.0
*/


//接口
require_once plugin_dir_path(__FILE__) . 'interface.php';
//创建一个菜单
function vuespa_create_menu_page()
{
    add_menu_page(
        'VueSpa选项',                   // 此菜单对应页面上显示的标题
        'VueSpa',                      // 要为此实际菜单项显示的文本
        'administrator',               // 哪种类型的用户可以看到此菜单
        'vuespa_id',                   //  此菜单项的唯一ID(即段塞)
        'vuespa_menu_page_display',    // 呈现此页面的菜单时要调用的函数的名称
        'dashicons-admin-customizer',  //图标 - 默认图标
        '500.1',                       //位置
    );
} // end vuespa_create_menu_page 
add_action('admin_menu', 'vuespa_create_menu_page');

//菜单回调 - 展示的内容
function vuespa_menu_page_display()
{
?>

    <!--在默认WordPress“包装”容器中创建标题-->
    <div class="wrap">
        <!--标题-->
        <h2><?php echo esc_html(get_admin_page_title()); ?></h2>
        <!--提供Vue挂载点-->
        <div id="vuespa">此内容将在挂载Vue后被替换{{data}}</div>
    </div>



<?php

    //展示准备的数据
    echo "<pre>";
    print_r(vuespa_data());
    echo "</pre>";

    echo "<h3>调用选项值</h3>";
    echo get_option('dataOne');
    echo "<br/>";
    echo get_option('dataTwo');
} // vuespa_menu_page_display



//载入所需 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');


//准备待传输的数据
function vuespa_data()
{
    $person = [
        "str" => "Hello, world! - Npcink",
        "num" => 25,
        "city" => [1, 2, 3, 4, 5],
    ];
    return $person;
}

interface.php

<?php
//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));
    }
}

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");

问题

目前的功能是可以用了,但还有些问题

  • 只能一对一的获取数据,在一些复杂场景中,这种数据结构很不友好
  • 目前是手动载入 Vue3 和 Axios文件,加载缓慢,导致页面都加载好了,选项内容有些许延迟,有闪动感,体验不好
  • 为了简单的功能,载入了 vue3 这个庞然大物,而且vue3的很多功能都没用上。
  • 没有人员筛选、文章筛选和分类筛选之类的,与 WordPress 产生交互的功能,

针对以上问题,我们将在下一节中继续进行优化改进。

教程

后台用户列表添加昵称显示 - WordPress添加小功能

2023-6-25 22:17:00

教程

第三节:Vue3 开发WordPress设置选项 - 从筛选功能研究前后台数据交互

2023-6-27 23:21:00

⚠️
Npcink上的部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 1355471563#qq.com 或点击右侧 私信:Muze 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索