手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

  • 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios已关闭评论
  • 205 次浏览
  • A+
所属分类:Web前端
摘要

项目同步git:https://gitee.com/lixin_ajax/vue3-vite-ts-pinia-vant-less.git  觉得有帮助的小伙伴请点下小心心哦

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

 觉得有帮助的小伙伴请点下小心心哦

 

为避免赘述,过于基础的点会直接省略或贴图,比如创建文件夹/文件的路径/路由一类

配置相应功能,也尽量只贴相关代码,并不代表整个文件内容

我会尽量把每一步都记录下来,让跟随文档操作的朋友也能还原项目

项目不尽完美,但是主体功能应该都可以有所参考

一.本地初始环境

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 

二.使用vite脚手架,创建vue3+ts

yarn create vite

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

输入项目名,回车确认

 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

选择Vue和TypeScript

 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 

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

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

yarn    // 安装依赖 yarn dev // 运行项目

 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

 

四.必备依赖

This package contains type definitions for Node.js (http://nodejs.org/)

yarn add @types/node -S -D

 

五.配置路径别名@

1.位置:直接改写vite.config.ts -- 顺便就添加alias

// vite.config.ts  import vue from "@vitejs/plugin-vue"; import { resolve } from "path";  function pathResolve(dir: string) {   return resolve(process.cwd(), ".", dir); }  // https://vitejs.dev/config/ export default () => {   return {     resolve: {       alias: [         {           find: "@",           replacement: pathResolve("src"),         },         {           find: "views",           replacement: pathResolve("src/views"),         },       ],     },     plugins: [vue()],   }; };

 

2.位置:tsconfig.json -- 修改baseUrl及paths

// tsconfig.json 
{
  "compilerOptions": {
     ......
  "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"],
      "views/*": ["src/views/*"],
      "components/*": ["src/components/*"],
      "assets/*": ["src/assets/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

 

六.配置vue-router

yarn add vue-router -S

推荐一个很好的插件nprogress【进度条】

yarn add @types/nprogress nprogress -D

main.ts引入router

// main.ts  import { createApp } from 'vue' import './style.css'  import App from './App.vue' import router from "./router";  const app = createApp(App as any); app.use(router)  app.mount('#app')

src下创建router文件夹,项目往往需要模块化,所以代码尽量不要杂糅在一起

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 /router/index.ts

/router/index.ts  import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"; import NProgress from "nprogress"; import "nprogress/nprogress.css";  const modules: any = import.meta.glob("./modules/**/*.ts", { eager: true });  const routes: Array<RouteRecordRaw> = []; for (const key in modules) {     routes.push(...modules[key].default); }  const router = createRouter({     history: createWebHashHistory(), // history 模式则使用 createWebHistory()     routes, });  router.beforeEach(async (_to, _from, next) => {     NProgress.start();     next(); });  router.afterEach((_to) => {     NProgress.done(); });  export default router;

/router/typings.d.ts 路由meta格式受控

/router/typing.d.ts  import "vue-router";  declare module "vue-router" {     interface RouteMeta {         // options           title?: string;         // every route must declare           show?: boolean; //     } }

然后就是test下随便创建一个路由,对应的,views下创建相应的vue文件,App.vue给上router-view

test/index.ts

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

app.vue

 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 test/index.vue

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

查看页面

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

页面正确显示,路由部署成功!

 

七.配置css预处理:less

yarn add less less-loader -D

为了配置全局的less样式文件,同时引入fs模块

yarn add fs -D

进入项目根目录的配置文件 

位置:vite.config.ts -- css

// vite.config.ts  import vue from "@vitejs/plugin-vue"; import { resolve } from "path"; import fs from 'fs'  function pathResolve(dir: string) {   return resolve(process.cwd(), ".", dir); }  // https://vitejs.dev/config/ export default () => {   const lessResources: Array<String> = []   fs.readdirSync('src/assets/styles').map((dirname) => {     if (fs.statSync(`src/assets/styles/${dirname}`).isFile()) {       lessResources.push(`@import "src/assets/styles/${dirname}";`)     }   })   return {     ......,
  // css     css: {       preprocessorOptions: {         less: {           charset: false,           additionalData: lessResources.join(''),           modifyVars: {             'primary-color': '#0080FF',             'link-color': '#0080FF',             'border-radius-base': '4px',           },           javascriptEnabled: true,         },       },     },   }; };

 

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

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 进入test/index.vue使用声明

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 查看页面

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

 

八.配置svg

yarn add vite-plugin-svg-icons -D

yarn add fast-glob -D

vite.config.ts引入插件
// vite.config.ts  import vue from "@vitejs/plugin-vue"; import { createSvgIconsPlugin } from "vite-plugin-svg-icons"; import path from "path";  // https://vitejs.dev/config/ export default () => {   return {     ......,     plugins: [       vue(),       createSvgIconsPlugin({         // 指定需要缓存的图标文件夹           iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],         // 指定symbolId格式           symbolId: "icon-[dir]-[name]",       }),     ],   }; };

根据config配置创建存放svg的目录文件,并创建SvgIcon组件

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 SvgIcon组件

// SvgIcon/index.vue  <template>     <svg aria-hidden="true" class="svg-icon">         <use :xlink:href="symbolId" :fill="color" />     </svg> </template>  <script lang="ts" setup> import { computed } from "vue";  const props = defineProps({     prefix: {         type: String,         default: "icon",     },     name: {         type: String,         required: true,     },     color: {         type: String,         default: "#333",     }, }); const symbolId = computed(() => `#${props.prefix}-${props.name}`); </script> <style lang="less" scoped> .svg-icon {     width: 1em;     height: 1em;     fill: v-bind(color);     vertical-align: middle;     color: v-bind(color); } </style>

在main.ts中注册SvgIcon为全局组件

// main.ts  import { createApp } from 'vue' import './style.css' import "virtual:svg-icons-register"; import SvgIcon from "@/components/SvgIcon/index.vue";  import App from './App.vue' import router from "./router";  const app = createApp(App as any); app.use(router)  app.mount('#app') app.component("SvgIcon", SvgIcon);

在test/index.vue中引入组件

// test/index.vue  <svg-icon name="test-vue" />

查看页面,测试是否成功

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 页面显示svg图标,svg组件配置成功!

 

九.配置pinia

pinia: 类似vuex的仓库
pinia-use-persist: 持久加密缓存pinia数据
yarn add pinia pinia-use-persist -S

main.ts中引入pinia

// main.ts  import { createApp } from 'vue' import { createPinia } from 'pinia' import { usePersist } from 'pinia-use-persist'  import App from './App.vue'  const app = createApp(App as any); const pinia = createPinia() pinia.use(usePersist) app.use(pinia)

src下创建store目录存放相关文件

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 /store/modules下存放项目不同模块需要通过pinia通信的数据,假装项目有一个test模块,存放了一个数据number

// store/modules/test/index.ts  import { defineStore } from "pinia";  interface stateType {   number: number; }  const useTestStore = defineStore("user", {   state: (): stateType => ({     number: 0,   }),    getters: {},    actions: {     setNumber(number: number): void {       this.number = number;     },   },    persist: {     enabled: true,     encryptionKey: "vueTest",   }, });  export { useTestStore };

store/index.ts引入各模块

// store/index.ts  import { createPinia } from "pinia"; import { useTestStore } from "./modules/test";  const pinia = createPinia();  export { useTestStore }; export default pinia;

回到test/index.vue,测试pinia配置是否成功

// test/index.vue  <template>     <!-- 测试pinia -->     <button @click="number += 1">{{ number }}</button>   </div> </template>  <script setup lang="ts"> import { computed } from 'vue' import { useTestStore } from '@/store'  const store = useTestStore() const number = computed<number>({   get() {     return store.number   },   set(value) {     store.setNumber(value)   }, }) </script>

点击按钮,刷新后查看页面是否变化

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

 

十.配置vant ui

vant ui:https://vant-contrib.gitee.io/vant/v4/#/zh-CN/home

yarn add vant 

这里再推荐一个插件,unplugin-vue-components【自动引入】,引入ui可以省去很多麻烦

yarn add unplugin-vue-components -D 

vite.config.ts中引入vant ui

// vite.config.ts  import vue from '@vitejs/plugin-vue'; import Components from 'unplugin-vue-components/vite'; import { VantResolver } from 'unplugin-vue-components/resolvers';  export default {   plugins: [     vue(),     Components({       resolvers: [VantResolver()],     }),   ], };

回到test/index.vue测试vant ui引入是否成功

// test/index.vue  <!-- 测试vant ui --> <div>   <van-button type="primary">vant button</van-button> </div>

刷新页面查看

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 

 

 按钮有样式,vant ui引入成功!

但是官方描述:Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在使用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此需要手动引入样式。

所以,这几个组件需要使用的话需要在main.ts中引入样式

// main.ts  // Toast import 'vant/es/toast/style'; // Dialog import 'vant/es/dialog/style'; // Notify import 'vant/es/notify/style'; // ImagePreview import 'vant/es/image-preview/style';

回到test/index.vue测试,示例toast

// test/index.vue  import { Toast } from 'vant'  Toast('使用vant')

查看页面

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 

 

 toast有样式,vant ui引入成功!

但是,使用vant ui多是移动端,所以还要做移动端做以下适配

参考: https://vant-contrib.gitee.io/vant/v4/#/zh-CN/advanced-usage

1.适配安全距离

根据vant ui提供,在根文件index.html修改

// index.html    <!-- 在 head 标签中添加 meta 标签,并设置 viewport-fit=cover 值 -->   <meta name="viewport"     content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />    <!-- 开启顶部安全区适配 -->   <van-nav-bar safe-area-inset-top />    <!-- 开启底部安全区适配 -->   <van-number-keyboard safe-area-inset-bottom />

2.Viewport 布局

postcss-px-to-viewport-8-plugin:postcss-px-to-viewport-8-plugin 是一款 PostCSS 插件,用于将 px 单位转化为 vw/vh 单位。

yarn add postcss-px-to-viewport-8-plugin -D

vite.config.ts中更改配置

// vite.config.ts  import pxtovw from 'postcss-px-to-viewport-8-plugin' const loder_pxtovw = pxtovw({ //这里是设计稿宽度 自己修改   viewportWidth: 375,   viewportUnit: 'vw' }) export default defineConfig({   ......,   css: {     postcss: {       plugins: [loder_pxtovw]     }   } })

创建一个types/index.d.ts,用于处理包括postcss-px-to-viewport-8-plugin一类的没有声明文件的依赖

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

// src/types/index.d.ts  declare module "postcss-px-to-viewport-8-plugin"

刷新页面,F12查看样式

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

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

 

十一.配置axios

yarn add axios 

 tsconfig.json:types里加上"vite/client"

// tsconfig.json  {   "compilerOptions": {     ......,     "types": ["vite/client", "vite-plugin-svg-icons/client"]   },   "include": [     "src/**/*.ts",     "src/**/*.d.ts",     "src/**/*.tsx",     "src/**/*.vue",     "*.ts",   ],   "exclude": ["node_modules", "dist"],   "references": [{ "path": "./tsconfig.node.json" }] }

src下创建axios请求文件

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 创建axios

// utils/http/axios/index.ts  import axios, {   AxiosInstance,   AxiosRequestConfig,   AxiosResponse,   AxiosError, } from "axios"; import { IResponse } from "./type";  // 如果请求超过 `timeout` 的时间,请求将被中断 axios.defaults.timeout = 5000;  const axiosInstance: AxiosInstance = axios.create({   baseURL: import.meta.env.VITE_APP_API_BASEURL + "", });  // axios实例拦截请求 axiosInstance.interceptors.request.use(   (config: AxiosRequestConfig) => {     // 配置headers     config.headers = {       ...config.headers,     };     return config;   },   (error: any) => {     return Promise.reject(error);   } );  // axios实例拦截响应 axiosInstance.interceptors.response.use(   // 请求成功   (response: AxiosResponse) => {     return response;   },   // 请求失败   (error: AxiosError) => {     const { response } = error;     console.error(response, "response error");     if (response) {       return Promise.reject(response.data);     }   } );  const request = <T = any>(config: AxiosRequestConfig): Promise<T> => {   const conf = config;   return new Promise((resolve) => {     axiosInstance       .request<any, AxiosResponse<IResponse>>(conf)       .then((res: AxiosResponse<IResponse>) => {         const {           data: { result },         } = res;         resolve(result as T);       });   }); };  export function get<T = any>(config: AxiosRequestConfig): Promise<T> {   return request({ ...config, method: "GET" }); }  export function post<T = any>(config: AxiosRequestConfig): Promise<T> {   return request({ ...config, method: "POST" }); }  export default request; export type { AxiosInstance, AxiosResponse };

// utils/http/axios/type.ts  export interface RequestOptions {     // Whether to process the request result     isTransformResponse?: boolean; }  // 返回res.data的interface export interface IResponse<T = any> {     code: number | string;     result: T;     data: T;     message: string;     status: string | number; }

根目录创建.env.development配置开发请求地址

// .env.development  # 开发环境  VITE_APP_API_BASEURL = 你的请求地址  NODE_ENV = development

vite.config.ts配置server

// vite.config.ts      server: {       hmr: { overlay: false }, // 禁用或配置 HMR 连接 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层             // 服务配置             port: 3030, // 类型: number 指定服务器端口;             open: false, // 类型: boolean | string在服务器启动时自动在浏览器中打开应用程序;             cors: false, // 类型: boolean | CorsOptions 为开发服务器配置 CORS。默认启用并允许任何源            host: "0.0.0.0", // IP配置,支持从IP启动            ["/api"]: {         target: process.env.VITE_APP_API_BASEURL,         changeOrigin: true,         rewrite: (path: string) => path.replace(new RegExp("^/api"), ""),       },     },

创建api存放目录

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

  创建一个api

// api/test/index.ts  import { post } from "@/utils/http/axios"; import { IResponse } from "@/utils/http/axios/type";  export interface LoginData {   username?: string;   password?: string; }  enum URL {   login = "/api/user_center/testLogin", }  /**  * @description: 用户登录  * @params {LoginData} params  * @return {Promise}  */  const login = async (data: LoginData) =>   post<IResponse>({ url: URL.login, data });  export { login };

回到test/index.vue调用api测试axios

// test/index.vue  <script setup lang="ts"> import { login } from '@/api/test'  login({}) </script>

回到页面,查看network

手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 接口请求成功,axios配置成功!

 最后,配置一下打包

// vite.config.ts  import { UserConfig, ConfigEnv, loadEnv } from "vite";  // https://vitejs.dev/config/ export default ({ command, mode }: ConfigEnv): UserConfig => {   const env = loadEnv(mode, __dirname);   return {     base: env.NODE_ENV === "development" ? "/" : "./",     build: {       outDir: "dist",       assetsDir: "assets", //指定静态资源存放路径         sourcemap: false, //是否构建source map 文件     },   }; };

启动dist,没问题!

 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

 

结语:

项目到此主体功能就已经配置完毕了,细节之处大家多多查看官网和众多网友的分享

项目还有很多不完善甚至错误的地方,踩坑还会继续,后续有时间还会继续优化,实际使用中还有很多地方需要改进

 

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