最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

第五節(jié):WordPress 通過 REST API 和 Vue3 開發(fā)設置選項 - 使用Vite打包JS資源

2023-06-30 15:13 作者:Npcink_牧澤  | 我要投稿

承接上文,我們將常用選項中的兩個功能給實現(xiàn)了,這一節(jié),我們將對 JS 資源進行打包,最終產物只有一個 JS 文件和一個 CSS 文件,可以極大的提升網頁加載速度,減少依賴。

打包后的文件中,就包含了 vue3 和 Axios 的代碼內容,不必通過URL 引入 vue3 的所有功能了。而且,在打包之前,還能對各種選項進行自定義的驗證,還能使用各種前端框架,對選項進行美化。

更重要的是,使用打包后的文件,可以明顯減少頁面卡頓。

  • 本系列代碼分享在 GitHub 中,希望能幫助大家理解

  • https://github.com/muze-page/vue-spa

本節(jié)流程


準備打包環(huán)境

  • Node.js 安裝配置 | 菜鳥教程 (runoob.com)

我們使用 Vite 進行打包,您需要提前安裝 node 環(huán)境,

創(chuàng)建環(huán)境

使用 VS Code 打開我們的vue-spa文件夾,通過Ctrl+~ 打開終端,輸入以下命令創(chuàng)建 Vue 3 項目

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

稍等片刻后,分別執(zhí)行以下幾個命令

  1. ?cd vites

  2. ?npm install

  3. ?npm run dev

會提示一個網址,


我們將其在瀏覽器中打開,即可看到如下顯示

我們同時按下 Ctrl+c 暫停當前運行,回到控制臺中。

安裝Axios

在控制臺中輸入以下命令,安裝 Axios

  1. npm install axios

安裝完成后,打開vites文件夾下的 package.json 文件即可看到如下提示


即代表您安裝成功了。

重寫index.js

現(xiàn)在,我們需要重寫 index.js 文件,我們在 vites/src/components/ 文件夾下,新建文件?Option.vue?文件。寫入以下內容

  1. <script setup>

  2. import { reactive, onMounted } from "vue";

  3. import axios from "axios";

  4. const siteData = dataLocal.data;


  5. //存儲獲取的值

  6. const getData = reactive({

  7. ?//存儲獲取的媒體庫值

  8. ?mediaList: [],

  9. });


  10. //存儲選項值

  11. const datas = reactive({

  12. ?dataOne: "",

  13. ?dataTwo: "",

  14. ?dataName: [],

  15. ?dataImage: "",

  16. ?dataSelectedImage: "",

  17. });


  18. //獲取數(shù)據

  19. const get_option = () => {

  20. ?axios

  21. ? ?.post(dataLocal.route + "pf/v1/get_option", datas, {

  22. ? ? ?headers: {

  23. ? ? ? ?"X-WP-Nonce": dataLocal.nonce,

  24. ? ? ? ?"Content-Type": "application/json",

  25. ? ? ?},

  26. ? ?})

  27. ? ?.then((response) => {

  28. ? ? ?const data = response.data;

  29. ? ? ?datas.dataOne = data.dataOne;

  30. ? ? ?datas.dataTwo = data.dataTwo;

  31. ? ? ?datas.dataName = data.dataName;

  32. ? ? ?datas.dataImage = data.dataImage;

  33. ? ? ?datas.dataSelectedImage = data.dataSelectedImage;

  34. ? ?})

  35. ? ?.catch((error) => {

  36. ? ? ?window.alert("連接服務器失敗或后臺讀取出錯!數(shù)據讀取失敗");

  37. ? ? ?console.log(error);

  38. ? ?});

  39. };


  40. //保存數(shù)據

  41. const update_option = () => {

  42. ?console.log(datas);

  43. ?axios

  44. ? ?.post(dataLocal.route + "pf/v1/update_option", datas, {

  45. ? ? ?headers: {

  46. ? ? ? ?"X-WP-Nonce": dataLocal.nonce,

  47. ? ? ?},

  48. ? ?})

  49. ? ?.then((response) => {

  50. ? ? ?alert("保存成功");

  51. ? ?})

  52. ? ?.catch((error) => {

  53. ? ? ?alert("保存失敗");

  54. ? ? ?console.log(error);

  55. ? ?});

  56. };


  57. //上傳圖片

  58. const upload_img = (file) => {

  59. ?const formData = new FormData();

  60. ?formData.append("file", file);

  61. ?return axios

  62. ? ?.post(dataLocal.route + "wp/v2/media", formData, {

  63. ? ? ?headers: {

  64. ? ? ? ?"X-WP-Nonce": dataLocal.nonce,

  65. ? ? ? ?"Content-Type": "multipart/form-data",

  66. ? ? ?},

  67. ? ?})

  68. ? ?.then((response) => {

  69. ? ? ?// 圖片上傳成功后的處理邏輯

  70. ? ? ?const data = response.data;

  71. ? ? ?//返回圖片URL

  72. ? ? ?return data.source_url;

  73. ? ?})

  74. ? ?.catch((error) => {

  75. ? ? ?console.error(error);

  76. ? ? ?// 圖片上傳失敗后的處理邏輯

  77. ? ?});

  78. };


  79. //處理圖片上傳事件

  80. const update_img = (event) => {

  81. ?const file = event.target.files[0];

  82. ?upload_img(file).then((url) => {

  83. ? ?//將拿到的圖片URL傳給圖片變量

  84. ? ?datas.dataImage = url;

  85. ?});

  86. };


  87. //清空選擇圖片

  88. const clear_img = () => {

  89. ?datas.dataImage = "";

  90. };


  91. //獲取媒體庫圖片

  92. const getMediaList = () => {

  93. ?axios

  94. ? ?.get(dataLocal.route + "wp/v2/media")

  95. ? ?.then((response) => {

  96. ? ? ?getData.mediaList = response.data;

  97. ? ?})

  98. ? ?.catch((error) => {

  99. ? ? ?console.error(error);

  100. ? ?});

  101. };


  102. //從媒體庫選中圖片

  103. const selectImage = (imageUrl) => {

  104. ?datas.dataSelectedImage = imageUrl;

  105. };


  106. //頁面初始加載

  107. onMounted(() => {

  108. ?//獲取選項值

  109. ?get_option();

  110. });

  111. </script>


  112. <template>

  113. ?<!--兩個輸入框-->

  114. ?文本框1:<input type="text" v-model="datas.dataOne" /><br />

  115. ?文本框2:<input type="text" v-model="datas.dataTwo" />

  116. ?<hr />

  117. ?<!--用戶選擇-->

  118. ?用戶選擇:<select v-model="datas.dataName" multiple>

  119. ? ?<option v-for="option in siteData.user" :key="option.id" :value="option.id">

  120. ? ? ?{{ option.name }}

  121. ? ?</option>

  122. ?</select>

  123. ?<p>你選擇了:{{ datas.dataName }}</p>

  124. ?<br />

  125. ?按住command(control)按鍵即可進行多選

  126. ?<hr />

  127. ?<!--圖片上傳-->

  128. ?<input type="file" @change.native="update_img" /><br />

  129. ?<button type="button" @click="clear_img">清理</button><br />

  130. ?<img :src="datas.dataImage" v-if="datas.dataImage" />

  131. ?<hr />

  132. ?<!--獲取媒體庫圖片-->

  133. ?<button @click="getMediaList">獲取媒體庫圖片</button>

  134. ?<div class="box">

  135. ? ?<div v-for="media in getData.mediaList" :key="media.id" style="float: left">

  136. ? ? ?<img :src="media.source_url" />

  137. ? ? ?<button @click="selectImage(media.source_url)">選擇</button>

  138. ? ?</div>

  139. ?</div>

  140. ?<h2>{{ datas.dataSelectedImage ? "已" : "未" }}選擇圖片</h2>

  141. ?<img :src="datas.dataSelectedImage" v-if="datas.dataSelectedImage" />

  142. ?<hr />


  143. ?<button class="button button-primary" @click="update_option">保存</button>

  144. </template>


  145. <style scoped>

  146. img {

  147. ?max-width: 150px;

  148. ?height: auto;

  149. ?vertical-align: top;

  150. }

  151. .box {

  152. ?max-width: 800px;

  153. ?display: flex;

  154. ?margin: 1em 0;

  155. }

  156. </style>

這里,對原有寫法在語法糖 setup 的幫助下,進行了部分重寫,再抽離了部分CSS樣式,使得整體的代碼更加健壯和容易維護了。

當然,還有更多方法可以優(yōu)化,為了便于講解,這里不再贅述。

修改 App.js

/vites/src/

模塊制作好了,我們在 App.vue 文件中導入,寫入以下內容

  1. <script setup>

  2. //import HelloWorld from "./components/HelloWorld.vue";

  3. import Option from "./components/Option.vue";

  4. </script>


  5. <template>

  6. ?<Option></Option>

  7. </template>


  8. <style scoped></style>

將我們寫的組件展示出來

修改main.js

/vites/src/

在之前的章節(jié)中,我們提前準備的ID 是?vuespa?,所以,需要修改下此文件為以下內容

  1. import { createApp } from 'vue'

  2. //import './style.css'

  3. import App from './App.vue'


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

在這里,我還把默認的 CSS 樣式給注釋了

修改 vite.config.js

/vites/src/

為了讓打包后的文件名與我們原有的文件名保持一致,我們需要修改下打包細節(jié),替換該文件為以下內容

  1. import { defineConfig } from "vite";

  2. import vue from "@vitejs/plugin-vue";


  3. // https://vitejs.dev/config/

  4. export default defineConfig({

  5. ?plugins: [vue()],

  6. ?build: {

  7. ? ?rollupOptions: {

  8. ? ? ?output: {

  9. ? ? ? ?// 指定 chunk 文件名(含導出的代碼)

  10. ? ? ? ?//chunkFileNames: 'js/[name].js',

  11. ? ? ? ?// 指定靜態(tài)資源文件名(不含導出的代碼)

  12. ? ? ? ?//assetFileNames: 'assets/[name].[ext]',

  13. ? ? ? ?entryFileNames: "index.js",

  14. ? ? ? ?assetFileNames: "[name][extname]",

  15. ? ? ? ?chunkFileNames: "[name].js",

  16. ? ? ?},

  17. ? ?},

  18. ?},

  19. });

這樣,打包后就會產出 index.js 和 index.css 文件了,而不會攜帶別的字符。

wordpress 會緩存部分 JS 資源,記得在 vue-spa.php 文件中修改 vuespa_load_vues() 函數(shù)的版本號

打包

打包的過程,就是優(yōu)化整合各代碼的過程,我們定位到 vites 文件夾下,輸入以下代碼進行打包。

  1. npm run build

完成后,如下所示


我們可以在如下位置找到打包后的文件

  1. /vites/dist/

導入

有了打包好的 JS 文件和 CSS 文件,現(xiàn)在,我們將其在菜單中導入,修改?vue-spa.php?文件中的函數(shù)vuespa_load_vues()為以下內容

  1. //載入所需 JS 和 CSS 資源 并傳遞數(shù)據

  2. function vuespa_load_vues($hook)

  3. {

  4. ? ?//判斷當前頁面是否是指定頁面,是則繼續(xù)加載

  5. ? ?if ('toplevel_page_vuespa_id' != $hook) {

  6. ? ? ? ?return;

  7. ? ?}

  8. ? ?//版本號

  9. ? ?$ver = '55';

  10. ? ?//加載到頁面頂部

  11. ? ?wp_enqueue_style('vite', plugin_dir_url(__FILE__) . 'vites/dist/index.css', array(), $ver, false);

  12. ? ?//加載到頁面底部

  13. ? ?wp_enqueue_script('vite', plugin_dir_url(__FILE__) . 'vites/dist/index.js', array(), $ver, true);


  14. ? ?$pf_api_translation_array = array(

  15. ? ? ? ?'route' => esc_url_raw(rest_url()), ? ? //路由

  16. ? ? ? ?'nonce' => wp_create_nonce('wp_rest'), //驗證標記

  17. ? ? ? ?'data' => vuespa_data(), ? ? ? ? ? ? ? //自定義數(shù)據

  18. ? ?);

  19. ? ?wp_localize_script('vite', 'dataLocal', $pf_api_translation_array); //傳給vite項目

  20. }

  21. //樣式加載到后臺

  22. add_action('admin_enqueue_scripts', 'vuespa_load_vues');

這里,我們無需手動載入 vue.js 和 Axios.js 文件了,打包后的 index.js 文件中,都準備好了,減少了不必要的資源開銷。

添加type屬性

注意,因為我們打包后的 index.js 文件,是一個模塊,需要給其添加一個 type 屬性才能正常生效。

我們在?vue-spa.php?文件底部,添加以下代碼,給導入的 index.js 添加type屬性,

  1. //模塊導入

  2. function add_type_attribute_to_script($tag, $handle)

  3. {

  4. ? ?// 在這里判斷需要添加 type 屬性的 JS 文件,比如文件名包含 xxx.js

  5. ? ?if (strpos($tag, 'index.js') !== false) {

  6. ? ? ? ?// 在 script 標簽中添加 type 屬性

  7. ? ? ? ?$tag = str_replace('<script', '<script type="module"', $tag);

  8. ? ?}

  9. ? ?return $tag;

  10. }

  11. add_filter('script_loader_tag', 'add_type_attribute_to_script', 10, 2);

效果如下:

  1. //使用函數(shù)前

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


  3. //使用函數(shù)后

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

補充

若您需要在本地進行開發(fā)和預覽,您可能需要以下幾個知識

修改 index.html

/vites/

修改文件為以下內容,

  1. <body>

  2. ? ?<div id="vuespa"></div>

  3. ? ?<script type="module" src="/src/main.js"></script>

  4. ?</body>

拿不到傳來的 dataLocal

dataLocal 的值是外部傳來的,vite 并不知道,您可以通過臨時添加以下內容,進行模仿,但記得,在打包前進行注釋。

  1. const dataLocal = {

  2. ?route: "http://localhost:5173/wp-json/",

  3. ?nonce: "asdf",

  4. ?data: {

  5. ? ?user: [

  6. ? ? ?{ id: 1, name: "111" },

  7. ? ? ?{ id: 2, name: "222" },

  8. ? ?],

  9. ?},

  10. };


vue-spa.php完整代碼

  1. <?php

  2. /*

  3. Plugin Name: Vue - SPA

  4. Plugin URI: https://www.npc.ink

  5. Description: 將vue構建的頁面嵌入WordPress 中并產生交互

  6. Author: Muze

  7. Author URI: https://www.npc.ink

  8. Version: 1.0.0

  9. */



  10. //接口

  11. require_once plugin_dir_path(__FILE__) . 'interface.php';


  12. //創(chuàng)建一個菜單

  13. function vuespa_create_menu_page()

  14. {

  15. ? ?add_menu_page(

  16. ? ? ? ?'VueSpa選項', ? ? ? ? ? ? ? ? ? // 此菜單對應頁面上顯示的標題

  17. ? ? ? ?'VueSpa', ? ? ? ? ? ? ? ? ? ? ?// 要為此實際菜單項顯示的文本

  18. ? ? ? ?'administrator', ? ? ? ? ? ? ? // 哪種類型的用戶可以看到此菜單

  19. ? ? ? ?'vuespa_id', ? ? ? ? ? ? ? ? ? // ?此菜單項的唯一ID(即段塞)

  20. ? ? ? ?'vuespa_menu_page_display', ? ?// 呈現(xiàn)此頁面的菜單時要調用的函數(shù)的名稱 'vuespa_menu_page_display'

  21. ? ? ? ?'dashicons-admin-customizer', ?//圖標 - 默認圖標

  22. ? ? ? ?'500.1', ? ? ? ? ? ? ? ? ? ? ? //位置

  23. ? ?);

  24. } // end vuespa_create_menu_page

  25. add_action('admin_menu', 'vuespa_create_menu_page');


  26. //菜單回調 - 展示的內容

  27. function vuespa_menu_page_display()

  28. {

  29. ?>


  30. ? ?<!--在默認WordPress“包裝”容器中創(chuàng)建標題-->

  31. ? ?<div class="wrap">

  32. ? ? ? ?<!--標題-->

  33. ? ? ? ?<h2><?php echo esc_html(get_admin_page_title()); ?></h2>

  34. ? ? ? ?<!--提供Vue掛載點-->

  35. ? ? ? ?<div id="vuespa">此內容將在掛載Vue后被替換{{data}}</div>

  36. ? ?</div>




  37. <?php


  38. ? ?//展示準備的數(shù)據

  39. ? ?echo "<pre>";

  40. ? ?print_r(vuespa_data());

  41. ? ?echo "</pre>";


  42. ? ?echo "<h3>調用選項值</h3>";

  43. ? ?echo get_option('dataOne');

  44. ? ?echo "<br/>";

  45. ? ?echo get_option('dataTwo');

  46. ? ?echo "<br/>";

  47. ? ?print_r(get_option('dataName'));

  48. ? ?echo "<br/>";

  49. ? ?echo get_option('dataImage');

  50. ? ?echo "<br/>";

  51. ? ?echo get_option('dataSelectedImage');

  52. } // vuespa_menu_page_display




  53. //載入所需 JS 和 CSS 資源 并傳遞數(shù)據

  54. function vuespa_load_vues($hook)

  55. {

  56. ? ?//判斷當前頁面是否是指定頁面,是則繼續(xù)加載

  57. ? ?if ('toplevel_page_vuespa_id' != $hook) {

  58. ? ? ? ?return;

  59. ? ?}

  60. ? ?//版本號

  61. ? ?$ver = '53';

  62. ? ?//加載到頁面頂部

  63. ? ?wp_enqueue_style('vite', plugin_dir_url(__FILE__) . 'vites/dist/index.css', array(), $ver, false);

  64. ? ?//加載到頁面底部

  65. ? ?wp_enqueue_script('vite', plugin_dir_url(__FILE__) . 'vites/dist/index.js', array(), $ver, true);


  66. ? ?$pf_api_translation_array = array(

  67. ? ? ? ?'route' => esc_url_raw(rest_url()), ? ? //路由

  68. ? ? ? ?'nonce' => wp_create_nonce('wp_rest'), //驗證標記

  69. ? ? ? ?'data' => vuespa_data(), ? ? ? ? ? ? ? //自定義數(shù)據

  70. ? ?);

  71. ? ?wp_localize_script('vite', 'dataLocal', $pf_api_translation_array); //傳給vite項目

  72. }

  73. //樣式加載到后臺

  74. add_action('admin_enqueue_scripts', 'vuespa_load_vues');



  75. //準備待傳輸?shù)臄?shù)據

  76. function vuespa_data()

  77. {

  78. ? ?$person = [

  79. ? ? ? ?"str" => "Hello, world! - Npcink",

  80. ? ? ? ?"num" => 25,

  81. ? ? ? ?"city" => [1, 2, 3, 4, 5],

  82. ? ? ? ?"user" => vuespa_get_user_meat(),

  83. ? ?];

  84. ? ?return $person;

  85. }



  86. //整理并提供用戶信息

  87. function vuespa_get_user_meat()

  88. {

  89. ? ?//獲取所有角色

  90. ? ?$editable_roles = wp_roles()->roles;

  91. ? ?$roles = array_keys($editable_roles);

  92. ? ?//獲取除了'subscriber'(訂閱者)角色之外的所有角色的用戶數(shù)據

  93. ? ?$subscriber_key = array_search('subscriber', $roles, true);

  94. ? ?if (false !== $subscriber_key) {

  95. ? ? ? ?$roles = array_slice($roles, 0, $subscriber_key);

  96. ? ?}


  97. ? ?$users = get_users(array('role__in' => $roles));


  98. ? ?//轉為關聯(lián)數(shù)組

  99. ? ?$user_data = array_map(function ($user) {

  100. ? ? ? ?return [

  101. ? ? ? ? ? ?'id' ? => $user->ID,

  102. ? ? ? ? ? ?'name' => $user->display_name,

  103. ? ? ? ?];

  104. ? ?}, $users);


  105. ? ?return $user_data;

  106. }


  107. //模塊導入

  108. function add_type_attribute_to_script($tag, $handle)

  109. {

  110. ? ?// 在這里判斷需要添加 type 屬性的 JS 文件,比如文件名包含 xxx.js

  111. ? ?if (strpos($tag, 'index.js') !== false) {

  112. ? ? ? ?// 在 script 標簽中添加 type 屬性

  113. ? ? ? ?$tag = str_replace('<script', '<script type="module"', $tag);

  114. ? ?}

  115. ? ?return $tag;

  116. }

  117. add_filter('script_loader_tag', 'add_type_attribute_to_script', 10, 2);

總結

本章節(jié)中,我們使用 Vite 對 index.js 文件進行了打包等處理,基于現(xiàn)在的 Node 生態(tài),您還可以

  • 使用 mockjs 提供攔截,更方便的進行本地開發(fā)

  • 使用現(xiàn)成的前端框架提升開發(fā)效率,例如 Element Plus

  • 使用 Pinia 進行數(shù)據的統(tǒng)一管理

  • 使用第三方庫,實現(xiàn)數(shù)據校驗

  • 使用TS約束變量類型,提升代碼健壯性

因篇幅原因,此處不再贅述。

下面是我使用 Element Plus 做出的下拉選項卡,比瀏覽器默認的好用多了

如果您能堅持看到這里,相信您也會有所收獲,希望您能基于此教程,做出更多有趣和實用的代碼來。

最新文章

  • 后續(xù)文章持續(xù)撰寫中,點個關注,獲取平臺最新文章推送。

  • 技術有限,還望諸位協(xié)助勘誤,于評論區(qū)指出,

  • 常一文多發(fā),最新勘定和增補文章于下方鏈接給出

  • https://www.npc.ink/277313.html


第五節(jié):WordPress 通過 REST API 和 Vue3 開發(fā)設置選項 - 使用Vite打包JS資源的評論 (共 條)

分享到微博請遵守國家法律
左云县| 青海省| 刚察县| 合水县| 太白县| 新绛县| 河南省| 深水埗区| 辽阳市| 雷山县| 辛集市| 南丹县| 抚顺县| 赞皇县| 友谊县| 英德市| 富民县| 罗甸县| 台中县| 昌江| 潮安县| 安徽省| 高邮市| 三河市| 阿拉尔市| 北川| 麟游县| 南陵县| 中西区| 皋兰县| 麻栗坡县| 阿城市| 邮箱| 浦北县| 通化县| 台江县| 苍南县| 靖远县| 新闻| 庆云县| 繁昌县|