第五节:Vue3 开发WordPress设置选项 - 使用Vite打包JS资源

承接上文,我们将常用选项中的两个功能给实现了,这一节,我们将对 JS 资源进行打包,最终产物只有一个 JS 文件和一个 CSS 文件,可以极大的提升网页加载速度,减少依赖。

打包后的文件中,就包含了 vue3 和 Axios 的代码内容,不必通过URL 引入 vue3 的所有功能了。而且,在打包之前,还能对各种选项进行自定义的验证,还能使用各种前端框架,对选项进行美化。

更重要的是,使用打包后的文件,可以明显减少页面卡顿。

  • 本系列代码分享在 GitHub 中,希望能帮助大家理解
  • https://github.com/muze-page/vue-spa

本节流程

03.png

准备打包环境

我们使用 Vite 进行打包,您需要提前安装 node 环境,

创建环境

使用 VS Code 打开我们的vue-spa文件夹,通过Ctrl+~ 打开终端,输入以下命令创建 Vue 3 项目

npm create vite@latest vites -- --template vue

稍等片刻后,分别执行以下几个命令

  cd vites
  npm install
  npm run dev

会提示一个网址,

00.png

我们将其在浏览器中打开,即可看到如下显示

01.png

我们同时按下 Ctrl+c 暂停当前运行,回到控制台中。

安装Axios

在控制台中输入以下命令,安装 Axios

npm install axios

安装完成后,打开vites文件夹下的 package.json 文件即可看到如下提示

02.png
即代表您安装成功了。

重写index.js

现在,我们需要重写 index.js 文件,我们在 vites/src/components/ 文件夹下,新建文件 Option.vue 文件。写入以下内容

<script setup>
import { reactive, onMounted } from "vue";
import axios from "axios";
const siteData = dataLocal.data;

//存储获取的值
const getData = reactive({
  //存储获取的媒体库值
  mediaList: [],
});

//存储选项值
const datas = reactive({
  dataOne: "",
  dataTwo: "",
  dataName: [],
  dataImage: "",
  dataSelectedImage: "",
});

//获取数据
const 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;
      datas.dataName = data.dataName;
      datas.dataImage = data.dataImage;
      datas.dataSelectedImage = data.dataSelectedImage;
    })
    .catch((error) => {
      window.alert("连接服务器失败或后台读取出错!数据读取失败");
      console.log(error);
    });
};

//保存数据
const update_option = () => {
  console.log(datas);
  axios
    .post(dataLocal.route + "pf/v1/update_option", datas, {
      headers: {
        "X-WP-Nonce": dataLocal.nonce,
      },
    })
    .then((response) => {
      alert("保存成功");
    })
    .catch((error) => {
      alert("保存失败");
      console.log(error);
    });
};

//上传图片
const upload_img = (file) => {
  const formData = new FormData();
  formData.append("file", file);
  return axios
    .post(dataLocal.route + "wp/v2/media", formData, {
      headers: {
        "X-WP-Nonce": dataLocal.nonce,
        "Content-Type": "multipart/form-data",
      },
    })
    .then((response) => {
      // 图片上传成功后的处理逻辑
      const data = response.data;
      //返回图片URL
      return data.source_url;
    })
    .catch((error) => {
      console.error(error);
      // 图片上传失败后的处理逻辑
    });
};

//处理图片上传事件
const update_img = (event) => {
  const file = event.target.files[0];
  upload_img(file).then((url) => {
    //将拿到的图片URL传给图片变量
    datas.dataImage = url;
  });
};

//清空选择图片
const clear_img = () => {
  datas.dataImage = "";
};

//获取媒体库图片
const getMediaList = () => {
  axios
    .get(dataLocal.route + "wp/v2/media")
    .then((response) => {
      getData.mediaList = response.data;
    })
    .catch((error) => {
      console.error(error);
    });
};

//从媒体库选中图片
const selectImage = (imageUrl) => {
  datas.dataSelectedImage = imageUrl;
};

//页面初始加载
onMounted(() => {
  //获取选项值
  get_option();
});
</script>

<template>
  <!--两个输入框-->
  文本框1:<input type="text" v-model="datas.dataOne" /><br />
  文本框2:<input type="text" v-model="datas.dataTwo" />
  <hr />
  <!--用户选择-->
  用户选择:<select v-model="datas.dataName" multiple>
    <option v-for="option in siteData.user" :key="option.id" :value="option.id">
      {{ option.name }}
    </option>
  </select>
  <p>你选择了:{{ datas.dataName }}</p>
  <br />
  按住command(control)按键即可进行多选
  <hr />
  <!--图片上传-->
  <input type="file" @change.native="update_img" /><br />
  <button type="button" @click="clear_img">清理</button><br />
  <img :src="datas.dataImage" v-if="datas.dataImage" />
  <hr />
  <!--获取媒体库图片-->
  <button @click="getMediaList">获取媒体库图片</button>
  <div class="box">
    <div v-for="media in getData.mediaList" :key="media.id" style="float: left">
      <img :src="media.source_url" />
      <button @click="selectImage(media.source_url)">选择</button>
    </div>
  </div>
  <h2>{{ datas.dataSelectedImage ? "已" : "未" }}选择图片</h2>
  <img :src="datas.dataSelectedImage" v-if="datas.dataSelectedImage" />
  <hr />

  <button class="button button-primary" @click="update_option">保存</button>
</template>

<style scoped>
img {
  max-width: 150px;
  height: auto;
  vertical-align: top;
}
.box {
  max-width: 800px;
  display: flex;
  margin: 1em 0;
}
</style>

这里,对原有写法在语法糖 setup 的帮助下,进行了部分重写,再抽离了部分CSS样式,使得整体的代码更加健壮和容易维护了。

当然,还有更多方法可以优化,为了便于讲解,这里不再赘述。

修改 App.js

/vites/src/

模块制作好了,我们在 App.vue 文件中导入,写入以下内容

<script setup>
//import HelloWorld from "./components/HelloWorld.vue";
import Option from "./components/Option.vue";
</script>

<template>
  <Option></Option>
</template>

<style scoped></style>

将我们写的组件展示出来

修改main.js

/vites/src/

在之前的章节中,我们提前准备的ID 是 vuespa ,所以,需要修改下此文件为以下内容

import { createApp } from 'vue'
//import './style.css'
import App from './App.vue'

createApp(App).mount('#vuespa')

在这里,我还把默认的 CSS 样式给注释了

修改 vite.config.js

/vites/src/

为了让打包后的文件名与我们原有的文件名保持一致,我们需要修改下打包细节,替换该文件为以下内容

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      output: {
        // 指定 chunk 文件名(含导出的代码)
        //chunkFileNames: 'js/[name].js',
        // 指定静态资源文件名(不含导出的代码)
        //assetFileNames: 'assets/[name].[ext]',
        entryFileNames: "index.js",
        assetFileNames: "[name][extname]",
        chunkFileNames: "[name].js",
      },
    },
  },
});

这样,打包后就会产出 index.js 和 index.css 文件了,而不会携带别的字符。

wordpress 会缓存部分 JS 资源,记得在 vue-spa.php 文件中修改 vuespa_load_vues() 函数的版本号

打包

打包的过程,就是优化整合各代码的过程,我们定位到 vites 文件夹下,输入以下代码进行打包。

npm run build

完成后,如下所示

04.png
我们可以在如下位置找到打包后的文件

/vites/dist/

导入

有了打包好的 JS 文件和 CSS 文件,现在,我们将其在菜单中导入,修改 vue-spa.php 文件中的函数vuespa_load_vues()为以下内容

//载入所需 JS 和 CSS 资源 并传递数据
function vuespa_load_vues($hook)
{
    //判断当前页面是否是指定页面,是则继续加载
    if ('toplevel_page_vuespa_id' != $hook) {
        return;
    }
    //版本号
    $ver = '55';
    //加载到页面顶部
    wp_enqueue_style('vite', plugin_dir_url(__FILE__) . 'vites/dist/index.css', array(), $ver, false);
    //加载到页面底部
    wp_enqueue_script('vite', plugin_dir_url(__FILE__) . 'vites/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');

这里,我们无需手动载入 vue.js 和 Axios.js 文件了,打包后的 index.js 文件中,都准备好了,减少了不必要的资源开销。

添加type属性

注意,因为我们打包后的 index.js 文件,是一个模块,需要给其添加一个 type 属性才能正常生效。

我们在 vue-spa.php 文件底部,添加以下代码,给导入的 index.js 添加type属性,

//模块导入
function add_type_attribute_to_script($tag, $handle)
{
    // 在这里判断需要添加 type 属性的 JS 文件,比如文件名包含 xxx.js
    if (strpos($tag, 'index.js') !== false) {
        // 在 script 标签中添加 type 属性
        $tag = str_replace('<script', '<script type="module"', $tag);
    }
    return $tag;
}
add_filter('script_loader_tag', 'add_type_attribute_to_script', 10, 2);

效果如下:

//使用函数前
<script  src='<http://localhost:10004/wp-content/plugins/vue-spa/vites/dist/index.js?ver=53>' id='vite-js'></script>

//使用函数后
<script type="module" src='<http://localhost:10004/wp-content/plugins/vue-spa/vites/dist/index.js?ver=53>' id='vite-js'></script>

补充

若您需要在本地进行开发和预览,您可能需要以下几个知识

修改 index.html

/vites/

修改文件为以下内容,

 <body>
    <div id="vuespa"></div>
    <script type="module" src="/src/main.js"></script>
  </body>

拿不到传来的 dataLocal

dataLocal 的值是外部传来的,vite 并不知道,您可以通过临时添加以下内容,进行模仿,但记得,在打包前进行注释。

const dataLocal = {
  route: "http://localhost:5173/wp-json/",
  nonce: "asdf",
  data: {
    user: [
      { id: 1, name: "111" },
      { id: 2, name: "222" },
    ],
  },
};

总结

本章节中,我们使用 Vite 对 index.js 文件进行了打包等处理,基于现在的 Node 生态,您还可以

  • 使用 mockjs 提供拦截,更方便的进行本地开发
  • 使用现成的前端框架提升开发效率,例如 Element Plus
  • 使用 Pinia 进行数据的统一管理
  • 使用第三方库,实现数据校验
  • 使用TS约束变量类型,提升代码健壮性

因篇幅原因,此处不再赘述。

下面是我使用 Element Plus 做出的下拉选项卡,比浏览器默认的好用多了

05.png

如果您能坚持看到这里,相信您也会有所收获,希望您能基于此教程,做出更多有趣和实用的代码来。

最新文章

  • 后续文章持续撰写中,点个关注,获取平台最新文章推送。
  • 技术有限,还望诸位协助勘误,于评论区指出,
  • 常一文多发,最新勘定和增补文章于下方链接给出
  • https://www.npc.ink/277313.html
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值