北冰洋以北 发表于 2024-10-9 10:24:13

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

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

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

https://i-blog.csdnimg.cn/blog_migrate/48624ef5d0f9d43558081f64d7692884.png

二.利用vite脚手架,创建vue3+ts
yarn create vite
https://i-blog.csdnimg.cn/blog_migrate/d92c06f3e3428cec91e00a8ed4bb16b1.png
输入项目名,回车确认

https://i-blog.csdnimg.cn/blog_migrate/18a0ee8b2366c0cf0dcf613357858a1b.png
选择Vue和TypeScript

https://i-blog.csdnimg.cn/blog_migrate/ded8d8a48390783f11b0c57ba969d43c.png
文件目次如下,项目创建成功!

https://i-blog.csdnimg.cn/blog_migrate/e3f2c2fb59ae27c6300add033867e474.png

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

https://i-blog.csdnimg.cn/blog_migrate/0ead5bc156fe5414be66a793df0a4a1a.png
yarn    // 安装依赖
yarn dev // 运行项目
https://i-blog.csdnimg.cn/blog_migrate/84fb835b9ca21b3137d101330f891066.png
浏览器打开地点,运行成功!

四.必备依赖
This package contains type definitions for Node.js (Node.js — Run JavaScript Everywhere)
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: ,
};
};
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文件夹,项目往往须要模块化,以是代码只管不要杂糅在一起

https://i-blog.csdnimg.cn/blog_migrate/ced9e5ff0ef2f68738f3081fd741e6bb.png
/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.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

https://i-blog.csdnimg.cn/blog_migrate/50a79a6069dc3aedc1668dc181f26f1d.png
app.vue

https://i-blog.csdnimg.cn/blog_migrate/a13f1b2b7ba3c7257c91efb00b6cc315.png
 test/index.vue

https://i-blog.csdnimg.cn/blog_migrate/04526678f0b1d4c99e625a82430217df.png
查看页面

https://i-blog.csdnimg.cn/blog_migrate/78712cc210f16b1bf5aa763b33d3bc04.png
页面正确表现,路由摆设成功!

七.配置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文件

https://i-blog.csdnimg.cn/blog_migrate/1533400b9f167488d1ea2fcff9736735.png
 进入index.less声明全局样式,测试less配置是否成功

https://i-blog.csdnimg.cn/blog_migrate/ed4e713285a79d029c0c6e8722bae921.png
 进入test/index.vue利用声明

https://i-blog.csdnimg.cn/blog_migrate/b20270c41d05c334a574df24c6d086a0.png
 查看页面

https://i-blog.csdnimg.cn/blog_migrate/7e35c148e7e6945fca387fe8b4eeb81e.png
盒子背景颜色改变,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: ,
      // 指定symbolId格式
        symbolId: "icon--",
      }),
    ],
};
}; 根据config配置创建存放svg的目次文件,并创建SvgIcon组件

https://i-blog.csdnimg.cn/blog_migrate/0770309c13134414664e6d4997726bf7.png
 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" /> 查看页面,测试是否成功

https://i-blog.csdnimg.cn/blog_migrate/53ee4a6521c396bd733402d74167f248.png
 页面表现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目次存放相关文件

https://i-blog.csdnimg.cn/blog_migrate/e68dfcb868a66ae3683683dd49626c9b.png
 /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> 点击按钮,革新后查看页面是否变革

https://i-blog.csdnimg.cn/blog_migrate/6b580208b32d8650b4ceca22dff8097d.png
页面数据没有初始化,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: ,
    }),
],
}; 回到test/index.vue测试vant ui引入是否成功
// test/index.vue

<!-- 测试vant ui -->
<div>
<van-button type="primary">vant button</van-button>
</div> 革新页面查看

https://i-blog.csdnimg.cn/blog_migrate/607116798dac0e793b1e9baf1bdc6cdd.png


 按钮有样式,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') 查看页面

https://i-blog.csdnimg.cn/blog_migrate/3dd2b94e9d83b78ada9cd745e429658d.png


 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" /> 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:
    }
}
}) 创建一个types/index.d.ts,用于处理惩罚包括postcss-px-to-viewport-8-plugin一类的没有声明文件的依赖

https://i-blog.csdnimg.cn/blog_migrate/673ec8a844b0f82cfdea226fa667a482.png
// src/types/index.d.ts

declare module "postcss-px-to-viewport-8-plugin" 革新页面,F12查看样式

https://i-blog.csdnimg.cn/blog_migrate/4d381085d5aff847fc41ffd08abc598f.png
 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哀求文件

https://i-blog.csdnimg.cn/blog_migrate/b48ee7a1abc35ea68d01cecf77417777.png
 创建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存放目次

https://i-blog.csdnimg.cn/blog_migrate/7a86686e2939132fead06472561c90b2.png
  创建一个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

https://i-blog.csdnimg.cn/blog_migrate/f90fcff78a91ba043a4f11989adac119.png
 接口哀求成功,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,没问题!

https://i-blog.csdnimg.cn/blog_migrate/6b2c26624cb01261a61e7170bbbd4f8d.png

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

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios