侧边栏壁纸
博主头像
杨不易呀

你的压力来源于无法自律,只是假装努力,现状跟不上内心欲望,所以你焦虑又恐慌。——杨不易呀

  • 累计撰写 72 篇文章
  • 累计创建 73 个标签
  • 累计收到 23 条评论

从零玩转系列之微信支付实战PC端项目构建Vue3+Vite+页面基础搭建

杨不易呀
2023-08-08 / 0 评论 / 0 点赞 / 707 阅读 / 4,990 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-08-22,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、前言

作者: 杨不易呀

欢迎来到本期的博客!在这篇文章中,我们将带您深入了解前端开发领域中的一个热门话题:

如何使用 Vue 3 和 Vite 构建前端项目。随着现代 Web 应用程序的需求不断演进,

选择适当的工具和技术变得至关重要。Vue 3 作为一种流行的前端框架,以其出色的性能和灵活的特性赢得了众多开发者的青睐。

而 Vite,则以其极速的开发体验和创新的构建方式在开发者中引起了极大的兴趣。

本次为前端知识点如果不懂前段可以去仓库直接copy出来使用,如果有什么问题可以在评论区留言,我会第一时间回复大家的.

在此之前已经更新了微信支付开篇、微信支付安全、微信实战基础框架搭建、本次更新为微信支付实战PC端接口搭建,实战篇分为几个章节因为代码量确实有点多哈.

注意: 如果不懂Vue语言没关系我会讲或直接Copy主要是学习如何实现的嘛

输入图片说明

本次项目使用技术栈

后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus

前端: Vue3、Vite、ElementPlus

小程序: Uniapp、Uview

演示地址查看 WEB端 小程序

二、介绍和环境搭建

背景和目的

在现代Web开发领域,构建高性能、交互丰富的前端应用程序已经成为一项关键任务。

Vue 3 和 Vite 分别作为前端开发的主要工具,为开发者提供了强大的能力和快速的开发体验。

Vue 3 作为一个流行的前端框架,引入了许多新特性和性能优化,使得构建现代应用更加高效。

而 Vite 作为一款创新性的构建工具,以其惊人的启动速度和开发体验成为了众多开发者的首选。

环境搭建

安装 Node.js 和 npm(如果尚未安装)

此处我建议可以使用nvm管理node版本非常nice,感兴趣的同学可以研究一下.

兼容性注意
Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,
当你的包管理器发出警告时,请注意升级你的 Node 版本。

搭建 Vite 项目

使用NPM:

  npm create vite@latest

使用 Yarn:

  yarn create vite

使用 PNPM:

  pnpm create vite

我这里就使用NPM来安装

注意: 第一次可能会弹出是否继续 直接Y 即可

  1. 执行 npm create vite@latest
  2. 自定义目录名称
    输入图片说明
  3. 选择模板 vite
    输入图片说明
  4. 选择语言 javaScript
    输入图片说明
  5. 进入新建的目录 npm install && npm run dev

如果很慢执行 npm install cnpm -g --registry=https://registry.npm.taobao.org

运行成功后会出现如下界面

输入图片说明

输入图片说明

项目结构

输入图片说明

查看

首先带大家看一下项目的效果图.

首页

输入图片说明

我的订单

输入图片说明

三、配置插件

新增开发插件

修改 package.json devDependencies

"devDependencies": {
"@vitejs/plugin-vue": "4.2.3",
"@vue/compiler-sfc": "3.3.2",
"prettier": "^2.8.8",
"sass": "1.62.1",
"unplugin-auto-import": "0.15.3",
"unplugin-vue-components": "^0.24.1",
"vite": "4.4.9",
"vite-plugin-compression": "0.5.1",
"vite-plugin-vue-setup-extend": "0.4.0"
}

插件介绍

  1. unplugin-vue-components
    • unplugin-vue-components 是一个用于 Vue.js 的构建工具,它旨在帮助开发者更轻松地引入和使用第三方 UI 组件库。
      它的设计理念是让你只引入你实际用到的组件,而不是整个组件库,从而减小最终打包的体积。
      这个工具可以帮助你自动按需引入和注册组件,而无需手动一个个引入,从而提高开发效率。通常情况下,
      你只需要在代码中写入组件的名称,unplugin-vue-components 就会根据需要自动引入组件代码并将其注册到 Vue 应用中。
  2. unplugin-auto-import
    • unplugin-auto-import 是一个用于 Vue.js 的构建工具,旨在简化组件和函数的自动引入和注册过程,从而提高开发效率。它允许你在代码中使用组件、函数或其他导出,而无需手动导入和注册,工具会自动为你处理这些步骤。
      具体来说,unplugin-auto-import 可以做以下事情:
      • 自动导入组件和函数:你只需要在代码中使用相应的组件或函数名称,工具会自动帮你查找并导入这些内容,无需手动编写导入语句。
      • 自动注册组件:工具会根据组件名称自动将其注册到 Vue 应用中,无需在代码中手动进行组件的注册操作。
      • 自动生成导入语句:在编辑器中使用组件或函数时,工具会自动生成导入语句,以便你可以获得智能提示和自动完成。
      • 智能提示和自动完成:通过自动引入和注册,你可以获得更好的智能提示和自动完成,提高代码编写的效率。
      • 减少冗余代码:工具会根据需要自动引入组件和函数,避免了不必要的冗余导入语句,从而减小最终打包的体积。
  3. vite-plugin-vue-setup-extend
    • vite-plugin-vue-setup-extend 是一个用于 Vite 构建工具的 Vue 插件,旨在增强 Vue 3 的 Composition API(组合式 API)在 Vite 项目中的使用体验。Composition API 是 Vue 3 引入的一种新的 API 风格,用于更灵活和可组合地处理组件逻辑。
      这个插件的目的是在 Vite 项目中扩展 Composition API 的使用,使开发者可以更方便地编写、组织和测试组件的逻辑。它可能提供了一些附加功能,例如:
      • 全局配置:允许您在整个应用中使用共享的 Composition API 配置,从而避免在每个组件中重复设置相同的逻辑。
      • 逻辑封装:可以将一些通用的逻辑封装成自定义的 Composition API 钩子,然后在多个组件中共享使用。
      • 状态管理集成:可能提供了与状态管理库(如 Vuex)的集成,以便更好地结合状态管理和 Composition API。
      • 便捷的工具函数:可能提供了一些便捷的工具函数,帮助您更轻松地处理副作用、异步请求等场景。

新增vite必须插件

修改 package.json dependencies

"dependencies": {
    "@vueuse/core": "10.1.2",
    "axios": "1.4.0",
    "core-js": "^3.6.5",
    "element-plus": "^2.3.9",
    "qrcode.vue": "^3.4.0",
    "sass": "^1.61.0",
    "vue": "^3.2.47",
    "vue-router": "4.2.0"
  },

插件介绍

  1. vue-router
    • vue-router 是 Vue.js 官方提供的路由管理库,用于实现前端单页面应用(Single Page Application,SPA)的导航和路由功能。
    • 它帮助开发者在 Vue 应用中实现页面间的切换、URL 路由管理以及路由参数的传递。
  2. axios
    • axios 是一个基于 Promise 的 JavaScript HTTP 客户端,用于在浏览器和 Node.js 环境中进行网络请求.
  3. element-plus
    • element-plus 是一个基于 Vue 3 的桌面端组件库,它是对 Element UI 的升级和重构,提供了一套更优雅的 UI 设计和更强大的功能。
  4. qrcode.vue
    • qrcode.vue 是一个基于 Vue 3 的二维码组件,它可以帮助你在 Vue 项目中快速生成二维码。
  5. sass
    • sass 是一个 CSS 预处理器,它扩展了 CSS 语言,增加了变量、嵌套规则、混合、导入等功能,使 CSS 更加强大和优雅。

运行 npm installcnpm install 重新下载依赖

在当前目录下创建vite/plugins文件夹

输入图片说明

在vite/plugins文件夹下创建autoImport.js

import autoImport from "unplugin-auto-import/vite";

export default function createAutoImport() {
   return autoImport({
      imports: ["vue", "vue-router"],
      dts: false,
   });
}

在vite/plugins文件夹下创建setup-extend.js

import setupExtend from "vite-plugin-vue-setup-extend";

export default function createSetupExtend() {
   return setupExtend();
}

在vite/plugins文件夹下创建index.js

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

import createAutoImport from "./auto-import";
import createSetupExtend from "./setup-extend";

export default function createVitePlugins(viteEnv, isBuild = false) {
   const vitePlugins = [
      vue({
         refTransform: true,
         reactivityTransform: true,
      }),
   ];
   vitePlugins.push(createAutoImport());
   vitePlugins.push(createSetupExtend());
   return vitePlugins;
}

以上配置文件用于可以不需要导入vue3内置属性,直接使用,自动导入

修改 vite.config.js

import { defineConfig, loadEnv } from "vite";
import path from "path";
import createVitePlugins from "./vite/plugins";

export default defineConfig(({ mode, command }) => {
   const env = loadEnv(mode, process.cwd());
   const { VITE_APP_ENV } = env;
   return {
      plugins: createVitePlugins(env, command === "build"),
      base: VITE_APP_ENV === "production" ? "/wx" : "/",
      resolve: {
         // https://cn.vitejs.dev/config/#resolve-alias
         alias: {
            "~": path.resolve(__dirname, "./"),
            "@": path.resolve(__dirname, "./src"),
         },
         // https://cn.vitejs.dev/config/#resolve-extensions
         extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
      },
      // vite 相关配置
      server: {
         port: 80,
         host: true,
         open: true,
         proxy: {
            // https://cn.vitejs.dev/config/#server-proxy
            "/wx-api": {
               target: "http://127.0.0.1:9080",
               changeOrigin: true,
               rewrite: (p) => p.replace(/^\/wx-api/, ""),
            },
         },
      },
      //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
      css: {
         postcss: {
            plugins: [
               {
                  postcssPlugin: "internal:charset-removal",
                  AtRule: {
                     charset: (atRule) => {
                        if (atRule.name === "charset") {
                           atRule.remove();
                        }
                     },
                  },
               },
            ],
         },
      },
   };
});

新增两个配置文件

.env.development

# 开发环境配置
ENV = 'development'

VUE_APP_BASE_API = '/wx-api'

.env.production

# 生产环境配置
ENV = 'production'

VUE_APP_BASE_API = '/wx-api'

上面这两个配置文件相当于Java当中的application-dev/prod.yml文件,用于配置不同环境下的配置文件

创建样式文件

由于样式文件太大则不进行展示,请自行下载

css 和 img 文件

assets

四、编写页面

ElementPlus 组件库

开发页面前我们肯定是要搞个UI组件

使用 ElementPlus 文档地址: https://element-plus.gitee.io/zh-CN/

输入图片说明

前面我们已经将依赖复制到了 package.json 里面并且 npm install 下载完成

显然还是不够的需要配置elelentPlus导入到系统当中

输入图片说明

修改 main.js 导入饿了么Ui并且将之前下载的依赖插件也导入进来

// main.ts
import {createApp} from "vue";
import ElementPlus from "element-plus";
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
import "element-plus/dist/index.css";
import "./assets/css/index.scss"; // global css
import "./styles/index.scss";
import App from "./App.vue";
// 引入路由器
import router from "./router";
// 二维码生成器
import QrcodeVue from "qrcode.vue";
// 注册指令
import plugins from "./plugins"; // plugins

const app = createApp(App);

app.use(ElementPlus, {
   locale: zhCn,
});
app.use(router);
app.use(plugins);
app.use(QrcodeVue);

app.mount("#app");

Vue Router

Vue.js 的官方路由 为 Vue.js 提供富有表现力、可配置的、方便的路由

用 Vue + Vue Router 创建单页应用非常简单:通过 Vue.js,我们已经用组件组成了我们的应用。当加入 Vue Router 时,我们需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们。

感兴趣的同学可以查看官方文档: https://router.vuejs.org/zh/introduction.html

输入图片说明

在src目录下面插件 route 文件夹 并且创建 index.js

import {
   createRouter,
   createWebHistory,
} from "vue-router";

// 编写页面跳转信息
const constantRoutes = [

];

const router = createRouter({
   history: createWebHistory(),
   routes: constantRoutes,
});

export default router;

解析页面结构

可以看到我们将要编写的页面是分别为三个层面

顶部: 菜单栏 分别有 三个选项也对应三个页面

中间: 内容区 显示不同的内容

底部: 信息区

输入图片说明

我们可以分别将顶部、底部抽出来为一个组件来调用

在src下创建 components 创建 AooHeader.vue 页面组合API

我这边已经为同学们写好了这种代码我们不写也罢要写就写核心

<template>
   <!-- 公共头 -->
   <header id="header">
      <section class="container">
         <ul class="nav">
            <router-link to="/wx/" tag="li" active-class="current" exact>
               <a>购买课程</a>
            </router-link>
            <router-link to="/wx/orders" tag="li" active-class="current">
               <a>我的订单</a>
            </router-link>
            <router-link to="/wx/download" tag="li" active-class="current">
               <a>下载账单</a>
            </router-link>
         </ul>
         <div class="clear"></div>
         <div class="toggleDarkBtn">
            <div style="text-align: right">
               <el-button
                       style="text-align: right"
                       color="#626aef"
                       :dark="isDark"
                       @click="toggleDarkBtn()"
               >
                  {{ toggleTitle }}
               </el-button>
               <el-button
                       class="btn2"
                       style="text-align: right"
                       color="#626aef"
                       @click="changeLanBtn()"
               >{{ lanTitle }}
               </el-button>
            </div>
         </div>
      </section>
   </header>
</template>
<script setup>
   import { isDark, toggleDark } from "@/composables";
   import { getCurrentInstance, ref } from "vue";

   const { proxy } = getCurrentInstance();

   // 声明触发的事件
   const emit = defineEmits(["changeLan"]);

   let lanTitle = ref("中文");
   let toggleTitle = ref("明亮");
   const toggleDarkBtn = () => {
      toggleTitle = toggleDark() ? "明亮" : "暗色";
   };
   const changeLanBtn = () => {
      lanTitle.value = lanTitle.value === "中文" ? "英文" : "中文";
      const lanVal = lanTitle.value !== "中文" ? "中文" : "英文";
      const modalVal =
              lanTitle.value !== "中文"
                      ? "切换全局组件为中文"
                      : "Switch global components to English";
      proxy.$modal.msgSuccess(modalVal);
      // 带参数触发父组件函数
      emit("changeLan", lanVal);
   };
   // 初始化
   changeLanBtn();
</script>
<style scoped lang="scss">
   .c-master {
      color: #68cb9b;
   }

   .bg-orange {
      background-color: #68cb9b;
   }

   .nav,
   .nav,
   .nav a {
      float: left;
   }

   .nav {
      padding: 15px 0 0 50px;
   }

   .nav,
   .nav a {
      float: left;
   }

   .nav a {
      border-bottom: 2px solid transparent;
      color: #666;
      display: block;
      font-size: 20px;
      line-height: 50px;
      padding: 0 10px;
      margin: 0 10px;
      transition: 0.3s;
      -webkit-transition: 0.3s;
   }

   .nav a:hover,
   .nav a {
      text-decoration: none;
   }

   .nav > .current a {
      border-color: var(--el-color-primary);
      color: var(--el-menu-text-color);
   }

   a {
      border-color: #68cb9b;
      color: #68cb9b;
   }

   .nav a {
      border-bottom: 2px solid transparent;
      color: #666;
      display: block;
      font-size: 20px;
      line-height: 50px;
      padding: 0 10px;
      margin: 0 10px;
      transition: 0.3s;
      -webkit-transition: 0.3s;
   }

   .toggleDarkBtn {
      margin-right: 60px;
      position: absolute;
      right: 0;
      top: 23px;
   }

   @media screen and (max-width: 500px) {
      .toggleDarkBtn {
         margin-top: 15px;
         /*width: 30%;*/
         margin-right: 20px;
      }

      .nav,
      .nav a {
         display: flex;
         justify-content: center;
         flex-wrap: nowrap;
         flex-direction: row;
         padding: 0;
         margin-left: 10px;
      }

      .container {
         padding: 0;
      }

      .toggleDarkBtn {
         width: min-content;
         margin-top: -30px;

         .btn2 {
            margin-top: 10px;
         }
      }
   }
</style>

在src下创建 components 创建 AooFooter.vue 页面组合API

<template>
  <!-- 公共底 -->
  <footer id="footer">
    <section>
      <div style="margin-top: -20px; padding: 30px; box-sizing: border-box">
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a></div>
        <div>个人博客: <a href="https://yby6.com">https:yby6.com</a>"</div>
        <div class="clear" />
      </div>
    </section>
  </footer>
</template>

编写完毕后还需要修改App.vue 将这两个组件全局化

我也给同学们编写好了直接使用

<template>
   <el-config-provider :locale="locale">
      <div class="app-container">
         <!-- 公共头 -->
         <AppHeader @changeLan="changeLan" />
         <!-- /公共头 -->
         <router-view />
      </div>
      <!-- 公共底 -->
      <AppFooter />
      <!-- /公共底 -->
   </el-config-provider>
</template>

<script setup name="App">
   import AppHeader from "./components/AppHeader";
   import AppFooter from "./components/AppFooter";

   import en from "element-plus/es/locale/lang/en";
   import zhCn from "element-plus/es/locale/lang/zh-cn";
   import {getCurrentInstance, ref} from "vue";

   const {proxy} = getCurrentInstance();

   const locale = ref(zhCn);

   function changeLan(lan) {
      if (lan === "中文") locale.value = zhCn;
      if (lan === "英文") locale.value = en;
   }

</script>
<style lang="scss">
   .app-container {
      width: 1200px;
      margin: 0 auto;
   }

   html.dark {
      color: white;
      background-color: #000;
   }

   @media screen and (max-width: 500px) {
      .app-container {
         width: auto;
         margin: 0 auto;
      }
   }
</style>

启动项目

npm run dev

输入图片说明

可以看到顶部 和 底部 都有了 还差内容区域了

在src目录下创建 views 文件夹在创建 index.vue 页面

<script setup>

</script>

<template>
   <div>
      我是index页面
   </div>
</template>

<style scoped lang="scss">

</style>

新增了一个页面咱们就要去route index.js当中新增路由信息

import {
   createRouter,
   createWebHistory,
} from "vue-router";
// 引入组件
import Index from "../views/index";

// path 表示访问地址 component 表示渲染的页面
const constantRoutes = [
   {
      path: "/",
      component: Index,
   },
   {
      path: "/wx",
      component: Index,
   }
];

const router = createRouter({
   history: createWebHistory(),
   routes: constantRoutes,
});

export default router;

然后 ctrl+s 保存 vite会自动刷新是不是贼舒服

查看效果

输入图片说明

我们的index页面显示出来了~

输入图片说明

最后

本期结束咱们下次再见👋~

,关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗

【选题思路】

“技术源于生活” 为什么写微信支付这种项目的文章呢? 因为我看到市面上的文章都不全面不细节不小白话更加没有配套Demo!!!

从而我的从零玩转微信支付诞生啦~ 搭配PC端、Uniapp端的不同实现.

【写作提纲】

一、前言

通过前言表达我每次的文章内容是什么东西和注意事项

二、介绍和环境搭建

介绍Vue3+Vite的强大Vue 3 作为一个流行的前端框架引入了许多新特性和性能优化,使得构建现代应用更加高效。

环境搭建使小白快速入手搭建前段Node环境

三、配置插件

主要是讲解Vue3当方便开发的插件和讲解插件的效果作用它是干什么的

四、编写页面

实战篇引入ElementPlus 组件库作为项目的整体UI、引入Vue Route路由管理、搭建第一个页面 Index 并且成功渲染页面

0
广告 广告

评论区