从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

打印 上一主题 下一主题

主题 806|帖子 806|积分 2418

项目同步git:vue3+vite+ts+pinia+vant+less: 空白的vue3架子,利用vant ui,适用于移动端一类的开发。 架子没有任何页面,基本无需删除任何代码,拉取便可直接用于开发。 假如有资助到各位朋友还请点个警惕心哦
 以为有资助的小伙伴请点下警惕心哦

为避免赘述,过于基础的点会直接省略或贴图,比如创建文件夹/文件的路径/路由一类
配置相应功能,也只管只贴相关代码,并不代表整个文件内容
我会只管把每一步都记录下来,让跟随文档操作的朋友也能还原项目
项目不尽完善,但是主体功能应该都可以有所参考
一.当地初始情况



二.利用vite脚手架,创建vue3+ts
  1. yarn create vite
复制代码


输入项目名,回车确认


选择Vue和TypeScript


文件目次如下,项目创建成功!



 三.启动项目:根据提示进入项目运行项目,或自行利用编码器输入指令进行启动


  1. yarn    // 安装依赖
  2. yarn dev // 运行项目
复制代码


浏览器打开地点,运行成功!

四.必备依赖
This package contains type definitions for Node.js (Node.js — Run JavaScript Everywhere)
  1. yarn add @types/node -S -D
复制代码

五.配置路径别名@
1.位置:直接改写vite.config.ts -- 顺便就添加alias
  1. // vite.config.ts
  2. import vue from "@vitejs/plugin-vue";
  3. import { resolve } from "path";
  4. function pathResolve(dir: string) {
  5.   return resolve(process.cwd(), ".", dir);
  6. }
  7. // https://vitejs.dev/config/
  8. export default () => {
  9.   return {
  10.     resolve: {
  11.       alias: [
  12.         {
  13.           find: "@",
  14.           replacement: pathResolve("src"),
  15.         },
  16.         {
  17.           find: "views",
  18.           replacement: pathResolve("src/views"),
  19.         },
  20.       ],
  21.     },
  22.     plugins: [vue()],
  23.   };
  24. };
复制代码

2.位置:tsconfig.json -- 修改baseUrl及paths
  1. // tsconfig.json
  2. {
  3.   "compilerOptions": {
  4.      ......
  5.   "baseUrl": "./",
  6.     "paths": {
  7.       "@/*": ["src/*"],
  8.       "views/*": ["src/views/*"],
  9.       "components/*": ["src/components/*"],
  10.       "assets/*": ["src/assets/*"]
  11.     }
  12.   },
  13.   "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  14.   "references": [{ "path": "./tsconfig.node.json" }]
  15. }
复制代码

六.配置vue-router
  1. yarn add vue-router -S
复制代码
推荐一个很好的插件nprogress【进度条】
  1. yarn add @types/nprogress nprogress -D
复制代码
main.ts引入router
  1. // main.ts
  2. import { createApp } from 'vue'
  3. import './style.css'
  4. import App from './App.vue'
  5. import router from "./router";
  6. const app = createApp(App as any);
  7. app.use(router)
  8. app.mount('#app')
复制代码
src下创建router文件夹,项目往往须要模块化,以是代码只管不要杂糅在一起


  1. /router/index.ts
  2. import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
  3. import NProgress from "nprogress";
  4. import "nprogress/nprogress.css";
  5. const modules: any = import.meta.glob("./modules/**/*.ts", { eager: true });
  6. const routes: Array<RouteRecordRaw> = [];
  7. for (const key in modules) {
  8.     routes.push(...modules[key].default);
  9. }
  10. const router = createRouter({
  11.     history: createWebHashHistory(), // history 模式则使用 createWebHistory()
  12.     routes,
  13. });
  14. router.beforeEach(async (_to, _from, next) => {
  15.     NProgress.start();
  16.     next();
  17. });
  18. router.afterEach((_to) => {
  19.     NProgress.done();
  20. });
  21. export default router;
  22. /router/typings.d.ts 路由meta格式受控
  23. /router/typing.d.ts
  24. import "vue-router";
  25. declare module "vue-router" {
  26.     interface RouteMeta {
  27.         // options
  28.           title?: string;
  29.         // every route must declare
  30.           show?: boolean; //
  31.     }
  32. }
复制代码
然后就是test下随便创建一个路由,对应的,views下创建相应的vue文件,App.vue给上router-view
test/index.ts


app.vue


 test/index.vue


查看页面


页面正确表现,路由摆设成功!

七.配置css预处理惩罚:less
  1. yarn add less less-loader -D
复制代码
为了配置全局的less样式文件,同时引入fs模块
  1. yarn add fs -D
复制代码
进入项目根目次的配置文件 
位置:vite.config.ts -- css
  1. // vite.config.ts
  2. import vue from "@vitejs/plugin-vue";
  3. import { resolve } from "path";
  4. import fs from 'fs'
  5. function pathResolve(dir: string) {
  6.   return resolve(process.cwd(), ".", dir);
  7. }
  8. // https://vitejs.dev/config/
  9. export default () => {
  10.   const lessResources: Array<String> = []
  11.   fs.readdirSync('src/assets/styles').map((dirname) => {
  12.     if (fs.statSync(`src/assets/styles/${dirname}`).isFile()) {
  13.       lessResources.push(`@import "src/assets/styles/${dirname}";`)
  14.     }
  15.   })
  16.   return {
  17.     ......,
  18.   // css
  19.     css: {
  20.       preprocessorOptions: {
  21.         less: {
  22.           charset: false,
  23.           additionalData: lessResources.join(''),
  24.           modifyVars: {
  25.             'primary-color': '#0080FF',
  26.             'link-color': '#0080FF',
  27.             'border-radius-base': '4px',
  28.           },
  29.           javascriptEnabled: true,
  30.         },
  31.       },
  32.     },
  33.   };
  34. };
复制代码

这里配置的公共less文件路径为src/assets/styles,创建styles文件夹和index.less文件


 进入index.less声明全局样式,测试less配置是否成功


 进入test/index.vue利用声明


 查看页面


盒子背景颜色改变,less及全局less配置成功!

八.配置svg
  1. yarn add vite-plugin-svg-icons -D
  2. yarn add fast-glob -D
复制代码
  1. vite.config.ts引入插件
复制代码
  1. // vite.config.ts
  2. import vue from "@vitejs/plugin-vue";
  3. import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
  4. import path from "path";
复制代码
  1. // https://vitejs.dev/config/
  2. export default () => {
  3.   return {
  4.     ......,
  5.     plugins: [
  6.       vue(),
  7.       createSvgIconsPlugin({
  8.         // 指定需要缓存的图标文件夹
  9.           iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
  10.         // 指定symbolId格式
  11.           symbolId: "icon-[dir]-[name]",
  12.       }),
  13.     ],
  14.   };
  15. };
复制代码
根据config配置创建存放svg的目次文件,并创建SvgIcon组件


 SvgIcon组件
  1. // SvgIcon/index.vue
  2. <template>
  3.     <svg aria-hidden="true" class="svg-icon">
  4.         <use :xlink:href="symbolId" :fill="color" />
  5.     </svg>
  6. </template>
  7. <script lang="ts" setup>
  8. import { computed } from "vue";
  9. const props = defineProps({
  10.     prefix: {
  11.         type: String,
  12.         default: "icon",
  13.     },
  14.     name: {
  15.         type: String,
  16.         required: true,
  17.     },
  18.     color: {
  19.         type: String,
  20.         default: "#333",
  21.     },
  22. });
  23. const symbolId = computed(() => `#${props.prefix}-${props.name}`);
  24. </script>
  25. <style lang="less" scoped>
  26. .svg-icon {
  27.     width: 1em;
  28.     height: 1em;
  29.     fill: v-bind(color);
  30.     vertical-align: middle;
  31.     color: v-bind(color);
  32. }
  33. </style>
复制代码
在main.ts中注册SvgIcon为全局组件
  1. // main.ts
  2. import { createApp } from 'vue'
  3. import './style.css'
  4. import "virtual:svg-icons-register";
  5. import SvgIcon from "@/components/SvgIcon/index.vue";
  6. import App from './App.vue'
  7. import router from "./router";
  8. const app = createApp(App as any);
  9. app.use(router)
  10. app.mount('#app')
  11. app.component("SvgIcon", SvgIcon);
复制代码
在test/index.vue中引入组件
  1. // test/index.vue
  2. <svg-icon name="test-vue" />
复制代码
查看页面,测试是否成功


 页面表现svg图标,svg组件配置成功!

九.配置pinia
  1. pinia: 类似vuex的仓库
  2. pinia-use-persist: 持久加密缓存pinia数据
复制代码
  1. yarn add pinia pinia-use-persist -S
复制代码
main.ts中引入pinia
  1. // main.ts
  2. import { createApp } from 'vue'
  3. import { createPinia } from 'pinia'
  4. import { usePersist } from 'pinia-use-persist'
  5. import App from './App.vue'
  6. const app = createApp(App as any);
  7. const pinia = createPinia()
  8. pinia.use(usePersist)
  9. app.use(pinia)
复制代码
src下创建store目次存放相关文件


 /store/modules下存放项目差异模块须要通过pinia通信的数据,冒充项目有一个test模块,存放了一个数据number
  1. // store/modules/test/index.ts
  2. import { defineStore } from "pinia";
  3. interface stateType {
  4.   number: number;
  5. }
  6. const useTestStore = defineStore("user", {
  7.   state: (): stateType => ({
  8.     number: 0,
  9.   }),
  10.   getters: {},
  11.   actions: {
  12.     setNumber(number: number): void {
  13.       this.number = number;
  14.     },
  15.   },
  16.   persist: {
  17.     enabled: true,
  18.     encryptionKey: "vueTest",
  19.   },
  20. });
  21. export { useTestStore };
复制代码
store/index.ts引入各模块
  1. // store/index.ts
  2. import { createPinia } from "pinia";
  3. import { useTestStore } from "./modules/test";
  4. const pinia = createPinia();
  5. export { useTestStore };
  6. export default pinia;
复制代码
回到test/index.vue,测试pinia配置是否成功
  1. // test/index.vue
  2. <template>
  3.     <!-- 测试pinia -->
  4.     <button @click="number += 1">{{ number }}</button>
  5.   </div>
  6. </template>
  7. <script setup lang="ts">
  8. import { computed } from 'vue'
  9. import { useTestStore } from '@/store'
  10. const store = useTestStore()
  11. const number = computed<number>({
  12.   get() {
  13.     return store.number
  14.   },
  15.   set(value) {
  16.     store.setNumber(value)
  17.   },
  18. })
  19. </script>
复制代码
点击按钮,革新后查看页面是否变革


页面数据没有初始化,pinia配置成功!

十.配置vant ui
vant ui:https://vant-contrib.gitee.io/vant/v4/#/zh-CN/home
  1. yarn add vant
复制代码
这里再推荐一个插件,unplugin-vue-components【自动引入】,引入ui可以省去很多贫苦
  1. yarn add unplugin-vue-components -D
复制代码
vite.config.ts中引入vant ui
  1. // vite.config.ts
  2. import vue from '@vitejs/plugin-vue';
  3. import Components from 'unplugin-vue-components/vite';
  4. import { VantResolver } from 'unplugin-vue-components/resolvers';
  5. export default {
  6.   plugins: [
  7.     vue(),
  8.     Components({
  9.       resolvers: [VantResolver()],
  10.     }),
  11.   ],
  12. };
复制代码
回到test/index.vue测试vant ui引入是否成功
  1. // test/index.vue
  2. <!-- 测试vant ui -->
  3. <div>
  4.   <van-button type="primary">vant button</van-button>
  5. </div>
复制代码
革新页面查看




 按钮有样式,vant ui引入成功!
但是官方描述:Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在利用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此须要手动引入样式。
以是,这几个组件须要利用的话须要在main.ts中引入样式
  1. // main.ts
  2. // Toast
  3. import 'vant/es/toast/style';
  4. // Dialog
  5. import 'vant/es/dialog/style';
  6. // Notify
  7. import 'vant/es/notify/style';
  8. // ImagePreview
  9. import 'vant/es/image-preview/style';
复制代码
回到test/index.vue测试,示例toast
  1. // test/index.vue
  2. import { Toast } from 'vant'
  3. Toast('使用vant')
复制代码
查看页面




 toast有样式,vant ui引入成功!
但是,利用vant ui多是移动端,以是还要做移动端做以下适配
参考: https://vant-contrib.gitee.io/vant/v4/#/zh-CN/advanced-usage
1.适配安全距离
根据vant ui提供,在根文件index.html修改
  1. // index.html
  2.   <!-- 在 head 标签中添加 meta 标签,并设置 viewport-fit=cover 值 -->
  3.   <meta name="viewport"
  4.     content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
复制代码
2.Viewport 布局
postcss-px-to-viewport-8-plugin:postcss-px-to-viewport-8-plugin 是一款 PostCSS 插件,用于将 px 单元转化为 vw/vh 单元。
  1. yarn add postcss-px-to-viewport-8-plugin -D
复制代码
vite.config.ts中更改配置
  1. // vite.config.ts
  2. import pxtovw from 'postcss-px-to-viewport-8-plugin'
  3. const loder_pxtovw = pxtovw({
  4. //这里是设计稿宽度 自己修改
  5.   viewportWidth: 375,
  6.   viewportUnit: 'vw'
  7. })
  8. export default defineConfig({
  9.   ......,
  10.   css: {
  11.     postcss: {
  12.       plugins: [loder_pxtovw]
  13.     }
  14.   }
  15. })
复制代码
创建一个types/index.d.ts,用于处理惩罚包括postcss-px-to-viewport-8-plugin一类的没有声明文件的依赖


  1. // src/types/index.d.ts
  2. declare module "postcss-px-to-viewport-8-plugin"
复制代码
革新页面,F12查看样式


 px已被转换,vant ui 及 移动端配置成功!

十一.配置axios
  1. yarn add axios
复制代码
 tsconfig.json:types里加上"vite/client"
  1. // tsconfig.json
  2. {
  3.   "compilerOptions": {
  4.     ......,
  5.     "types": ["vite/client", "vite-plugin-svg-icons/client"]
  6.   },
  7.   "include": [
  8.     "src/**/*.ts",
  9.     "src/**/*.d.ts",
  10.     "src/**/*.tsx",
  11.     "src/**/*.vue",
  12.     "*.ts",
  13.   ],
  14.   "exclude": ["node_modules", "dist"],
  15.   "references": [{ "path": "./tsconfig.node.json" }]
  16. }
复制代码
src下创建axios哀求文件


 创建axios
  1. // utils/http/axios/index.ts
  2. import axios, {
  3.   AxiosInstance,
  4.   AxiosRequestConfig,
  5.   AxiosResponse,
  6.   AxiosError,
  7. } from "axios";
  8. import { IResponse } from "./type";
  9. // 如果请求超过 `timeout` 的时间,请求将被中断
  10. axios.defaults.timeout = 5000;
  11. const axiosInstance: AxiosInstance = axios.create({
  12.   baseURL: import.meta.env.VITE_APP_API_BASEURL + "",
  13. });
  14. // axios实例拦截请求
  15. axiosInstance.interceptors.request.use(
  16.   (config: AxiosRequestConfig) => {
  17.     // 配置headers
  18.     config.headers = {
  19.       ...config.headers,
  20.     };
  21.     return config;
  22.   },
  23.   (error: any) => {
  24.     return Promise.reject(error);
  25.   }
  26. );
  27. // axios实例拦截响应
  28. axiosInstance.interceptors.response.use(
  29.   // 请求成功
  30.   (response: AxiosResponse) => {
  31.     return response;
  32.   },
  33.   // 请求失败
  34.   (error: AxiosError) => {
  35.     const { response } = error;
  36.     console.error(response, "response error");
  37.     if (response) {
  38.       return Promise.reject(response.data);
  39.     }
  40.   }
  41. );
  42. const request = <T = any>(config: AxiosRequestConfig): Promise<T> => {
  43.   const conf = config;
  44.   return new Promise((resolve) => {
  45.     axiosInstance
  46.       .request<any, AxiosResponse<IResponse>>(conf)
  47.       .then((res: AxiosResponse<IResponse>) => {
  48.         const {
  49.           data: { result },
  50.         } = res;
  51.         resolve(result as T);
  52.       });
  53.   });
  54. };
  55. export function get<T = any>(config: AxiosRequestConfig): Promise<T> {
  56.   return request({ ...config, method: "GET" });
  57. }
  58. export function post<T = any>(config: AxiosRequestConfig): Promise<T> {
  59.   return request({ ...config, method: "POST" });
  60. }
  61. export default request;
  62. export type { AxiosInstance, AxiosResponse };
  63. // utils/http/axios/type.ts
  64. export interface RequestOptions {
  65.     // Whether to process the request result
  66.     isTransformResponse?: boolean;
  67. }
  68. // 返回res.data的interface
  69. export interface IResponse<T = any> {
  70.     code: number | string;
  71.     result: T;
  72.     data: T;
  73.     message: string;
  74.     status: string | number;
  75. }
复制代码
根目次创建.env.development配置开发哀求地点
  1. // .env.development
  2. # 开发环境
  3. VITE_APP_API_BASEURL = 你的请求地址
  4. NODE_ENV = development
  5. vite.config.ts配置server
  6. // vite.config.ts
  7.     server: {
  8.       hmr: { overlay: false }, // 禁用或配置 HMR 连接 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层
  9.             // 服务配置
  10.             port: 3030, // 类型: number 指定服务器端口;
  11.             open: false, // 类型: boolean | string在服务器启动时自动在浏览器中打开应用程序;
  12.             cors: false, // 类型: boolean | CorsOptions 为开发服务器配置 CORS。默认启用并允许任何源
  13.            host: "0.0.0.0", // IP配置,支持从IP启动
  14.            ["/api"]: {
  15.         target: process.env.VITE_APP_API_BASEURL,
  16.         changeOrigin: true,
  17.         rewrite: (path: string) => path.replace(new RegExp("^/api"), ""),
  18.       },
  19.     },
复制代码
创建api存放目次


  创建一个api
  1. // api/test/index.ts
  2. import { post } from "@/utils/http/axios";
  3. import { IResponse } from "@/utils/http/axios/type";
  4. export interface LoginData {
  5.   username?: string;
  6.   password?: string;
  7. }
  8. enum URL {
  9.   login = "/api/user_center/testLogin",
  10. }
  11. /**
  12. * @description: 用户登录
  13. * @params {LoginData} params
  14. * @return {Promise}
  15. */
  16. const login = async (data: LoginData) =>
  17.   post<IResponse>({ url: URL.login, data });
  18. export { login };
复制代码
回到test/index.vue调用api测试axios
  1. // test/index.vue
  2. <script setup lang="ts">
  3. import { login } from '@/api/test'
  4. login({})
  5. </script>
复制代码
回到页面,查看network


 接口哀求成功,axios配置成功!
 最后,配置一下打包
  1. // vite.config.ts
  2. import { UserConfig, ConfigEnv, loadEnv } from "vite";
  3. // https://vitejs.dev/config/
  4. export default ({ command, mode }: ConfigEnv): UserConfig => {
  5.   const env = loadEnv(mode, __dirname);
  6.   return {
  7.     base: env.NODE_ENV === "development" ? "/" : "./",
  8.     build: {
  9.       outDir: "dist",
  10.       assetsDir: "assets", //指定静态资源存放路径
  11.         sourcemap: false, //是否构建source map 文件
  12.     },
  13.   };
  14. };
复制代码
启动dist,没问题!



结语:
项目到此主体功能就已经配置完毕了,细节之处大家多多查看官网和众多网友的分享
项目另有很多不美满甚至错误的地方,踩坑还会继续,后续有时间还会继续优化,现实利用中另有很多地方须要改进

项目同步git:https://gitee.com/lixin_ajax/vue3-vite-ts-pinia-vant-less.git

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

北冰洋以北

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表