vite-vue-ts精简模版集成pinia+svg+router+@src

话不多说,先创建vue-ts模版,

npm create vite@latest my-vite-vue-ts -- --template vue-ts

 

 

安装其他依赖:

npm i vue-router  sass sass-loader pinia   element-plus axios @element-plus/icons-vue fast-glob vite-plugin-svg-icons

npm install --save @types/nprogress

 修改 main.ts

import { createApp } from 'vue'
import App from './App.vue'

//引入 pinia store
import { createPinia } from 'pinia'
 
//引入 element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' 

import Router from '@/router' 
import   '@/router/beforeEach' 

//引入 vite-plugin-svg-icons
import 'virtual:svg-icons-register' 
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
import * as Icons from  '@element-plus/icons-vue' 



const pinia = createPinia()
const app =createApp(App) 
// 注册svgIcon为全局组件
app.component('svg-icon', SvgIcon)
// 注册全局组件
Object.keys(Icons).forEach(key => {
    app.component(key, Icons[key as keyof typeof Icons])
    // console.log(key); 
  }) 

app.use(pinia)
app.use(ElementPlus)
app.use(Router)
app.mount('#app')

修改 vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import { resolve } from "path";

export default defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
      // 指定需要缓存的图标文件夹
      iconDirs: [resolve(process.cwd(), "src/icons/svg")],
      // 指定symbolId格式
      symbolId: "icon-[dir]-[name]",

      /**
       * custom dom id
       * @default: __svg__icons__dom__
       */
      customDomId: "__svg__icons__dom__",
    }),
  ],
  resolve: {
    // 配置别名
    alias: {
      "@": resolve(__dirname, "./src"),
    },
  },
  //启动服务配置
  server: {
    host: "0.0.0.0",
    port: 8000,
    open: true,
    https: false,
    proxy: {},
  },
  // 生产环境打包配置
  //去除 console debugger
  build: {
    minify: "terser",
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
  },
});

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],

    "allowSyntheticDefaultImports": true, 
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }],
  "exclude": ["node_modules", "dist"] 
}

 package

{
  "name": "my-vite-vue-ts",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^1.1.4",
    "@types/nprogress": "^0.2.0",
    "axios": "^0.26.1",
    "element-plus": "^2.1.4",
    "fast-glob": "^3.2.11", 
    "pinia": "^2.0.12",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "vite-plugin-svg-icons": "^2.0.1",
    "vue": "^3.2.25",
    "vue-router": "^4.0.14"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.2.0",
    "typescript": "^4.5.4",
    "vite": "^2.8.0",
    "vue-tsc": "^0.29.8"
  }
}

 app.vue

<script lang="ts"> 
import HelloWorld from "./components/HelloWorld.vue"; 
import { defineComponent, ref } from "vue";
export default defineComponent({
  // 已启用类型推断
  props: {
    // testA : String, 
  },
  components: {
    HelloWorld,
  },
  setup() {
    return {};
  },
});
</script>

<template>
  <img alt="Vue logo" src="./assets/logo.png" />  
  <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

router/index.ts

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

const modules = import.meta.glob("../views/*/*.vue");
for (const path in modules) {
  modules[path]().then((mod) => {
    console.log(path, mod);
  });
}

const Router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: "/login",
      component: modules["../views/login/index.vue"],
    },
    {
      path: "/",
      component: modules["../views/dashboard/index.vue"],
    },
  ],
});

export default Router;

router/beforEach.ts

import router from "./index";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { RouteLocationNormalized } from "vue-router";

NProgress.configure({ showSpinner: false });

router.beforeEach(
  async (
    to: RouteLocationNormalized,
    _: RouteLocationNormalized,
    next: any
  ) => {
    // Start progress bar
    NProgress.start();
    console.log(
      "------router.beforeEach and nprogress is working---------------"
    );
    next();
  }
);

router.afterEach((to: RouteLocationNormalized) => {
  NProgress.done();
});

components/SvgIcon/index.vue

<template>
  <div
    v-if="isExternal"
    :style="styleExternalIcon"
    class="svg-external-icon svg-icon"
  />
  <svg v-else :class="svgClass" aria-hidden="true">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script lang="ts"> 
import { defineComponent, computed } from "vue";
import { isExternal } from "@/utils/validate";

export default defineComponent({
  name: "SvgIcon",
  props: {
    iconClass: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: "",
    },
  },
  computed: {
    isExternal() {
      return isExternal(this.iconClass);
    },
    iconName() {
      return `#icon-${this.iconClass}`;
    },
    svgClass() {
      if (this.className) {
        return "svg-icon " + this.className;
      } else {
        return "svg-icon";
      }
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        "-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`,
      };
    },
  },
});
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover !important;
  display: inline-block;
}
</style>

views/dashboard/index.vue

<template>
  <div class="dashborad">
    dashborad
    <p>
      <router-link to="/login">
        <span class="text">Red -- sass is working </span>
      </router-link>
    </p>
    <p>
      <el-button type="primary"
        >Button element is working---------------</el-button
      >
    </p>
    <p>
      <span>
        <svg-icon :icon-class="'eye'" :class-name="'abc'" /> svgIcon is working---------------
        
      </span>
    </p>

    <p>
       
      <el-icon :size="20"><alarm-clock /></el-icon>
      el-icon is working---------------
    </p>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { usemainStore } from "@/store/index";

export default defineComponent({
  data() {
    const mainStore = usemainStore();
    console.log(
      "------router is working---------------" + this.helloWorld + this.count
    );
    mainStore.changeState();
    return {};
  },
  watch: {},
  mounted() {},
  methods: {},
});
</script>

<style lang="scss">
.dashborad {
  font-size: 20px;
  .text {
    color: red;
  }
}
</style>

 npm run dev 可以正常跑起来。接下来。 

 接下来添加mock

修改main.ts

import '@/mock/login'

 添加*.d.ts

declare module 'mockjs';

添加src/mock/login.ts 

import Mock from "mockjs";

Mock.mock("/api/login", "post", function (params: String) {
  return {
    code: 200,
    data: "xxx",
    msg: "success",
  };
});

修改dashboard.vue

  mounted() {
    const mainStore = usemainStore();
    mainStore.changeState();
  },

修改changeState

 changeState() {
      this.count++;
      this.helloWorld = "haha";
      console.log(
        "------pinia is working---------------" + this.helloWorld + this.count
      );
      loginApi
        .login({
          userName: "a",
          passWord: "a",
        })
        .then((res) => {
          console.log(res);
        });
    },

添加loginApi

import http from "@/service/http";
import * as T from "./types";

const loginApi: T.ILoginApi = {
  login(params) {
      console.log("start post ");
      
    return http.post("/login", params);
  },
};
export default loginApi;

export interface ILoginParams {
  userName: string;
  passWord: string | number;
}
export interface ILoginApi {
  login: (params: ILoginParams) => Promise<any>;
}

http.ts

//http.ts
import axios, { AxiosRequestConfig } from "axios";
import NProgress from "nprogress";

// 设置请求头和请求路径
axios.defaults.baseURL = "/api";
axios.defaults.timeout = 10000;
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
axios.interceptors.request.use(
  (config): AxiosRequestConfig<any> => {
    const token = window.sessionStorage.getItem("token");
    if (token) {
      //@ts-ignore
      config.headers.token = token;
    }
    return config;
  },
  (error) => {
    return error;
  }
);
// 响应拦截
axios.interceptors.response.use((res) => {
  if (res.data.code === 111) {
    sessionStorage.setItem("token", ""); // token过期操作
  }
  return res;
});

interface ResType<T> {
  code: number;
  data?: T;
  msg: string;
  err?: string;
}
interface Http {
  get<T>(url: string, params?: unknown): Promise<ResType<T>>;
  post<T>(url: string, params?: unknown): Promise<ResType<T>>;
  upload<T>(url: string, params: unknown): Promise<ResType<T>>;
  download(url: string): void;
}

const http: Http = {
  get(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      axios
        .get(url, { params })
        .then((res) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  post(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      axios
        .post(url, JSON.stringify(params))
        .then((res) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      axios
        .post(url, file, {
          headers: { "Content-Type": "multipart/form-data" },
        })
        .then((res) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  download(url) {
    const iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = url;
    iframe.onload = function () {
      document.body.removeChild(iframe);
    };
    document.body.appendChild(iframe);
  },
};
export default http;

 package.json

{
  "name": "my-vite-vue-ts",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^1.1.4",
    "@types/nprogress": "^0.2.0",
    "axios": "^0.26.1",
    "element-plus": "^2.1.4",
    "fast-glob": "^3.2.11", 
    "pinia": "^2.0.12",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "vite-plugin-svg-icons": "^2.0.1",
    "vue": "^3.2.25",
    "vue-router": "^4.0.14"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.2.0",
    "typescript": "^4.5.4",
    "vite": "^2.8.0",
    "vue-tsc": "^0.29.8"
  }
}

 结果拦截成功。本文到此结束。需要源码打包的看下面链接。没分的留言。

vite-vue-ts精简模版集成pinia+svg+router+@src-Typescript文档类资源-CSDN下载本源码已经调试通过集成Vite-vue-ts集成pinia+svg+router+@srca更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/ldy889/85018930

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东宇科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值