vite+vue3+TypeScript 搭建项目基本框架

1 参考文档

参考1:基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)
参考2:vite+vue3+ts 手把手教你创建一个vue3项目

2 所有步骤

  1. 创建vue3项目
  2. 配置src别名为@、src/components别名为@_c
  3. 安装less/scss
  4. 安装ESLint
  5. 安装Prettier
  6. 自动导入
  7. 安装router
  8. 安装pinia【vue-devtools插件、数据持久化插件 这两个先不装】
  9. 安装axios
  10. 自定义组件名setup语法糖
  11. 安装element-plus组件库
  12. 安装Ant Design Vue组件库【可选】
  13. 安装与使用Echarts

3 具体步骤

webstorm配置import/export代码有空格

在这里插入图片描述

3.1 创建vue3项目

NPM方式

npm create vite@latest
  1. 填写项目名称
  2. 选择前端框架【选Vue】
  3. 选择开发语言【TypeScript】

3.2 配置src别名为@、src/components别名为@_c

在vite配置src别名为@、src/components别名为@_c,这能在开发时对路径看些来直观点。

  1. 打开 vite.config.ts 文件

    • 导入path模块
    • 加入 解析配置
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    //1、 导入 path 模块,帮助我们解析路径
    import { resolve } from 'path'
    
    // https://vitejs.dev/config/
    export default defineConfig({
        plugins: [
            vue(),
        ],
    
        //1、 ↓解析配置
        resolve: {
            // ↓路径别名
            alias: {
                "@": resolve(__dirname, "./src"),
                "_c": resolve(__dirname, "./src/components")
            }
        }
    })
    
  2. 打开 tsconfig.json 文件

    配置baseUrl,paths参数

    {
      "compilerOptions": {
        "target": "ES2020",
        "useDefineForClassFields": true,
        "module": "ESNext",
        "lib": [
          "ES2020",
          "DOM",
          "DOM.Iterable"
        ],
        "skipLibCheck": true,
        /* Bundler mode */
        "moduleResolution": "bundler",
        "allowImportingTsExtensions": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "preserve",
        /* Linting */
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noFallthroughCasesInSwitch": true,
        // 配置@别名 start
        "baseUrl": ".",
        "paths": {
          "@/*": [
            "src/*"
          ],
          "_c/*": [
            "src/components/*"
          ]
        }
        // 配置@别名 end
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.d.ts",
        "src/**/*.tsx",
        "src/**/*.vue"
      ],
      "references": [
        {
          "path": "./tsconfig.node.json"
        }
      ]
    }
    
  3. 使用方式

    重新运行一遍即可

3.3 安装less/scss

由于是使用vite,vite它提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持,但必须安装相应的预处理器依赖;
国内一般只使用 less 或 scss,所以我只写这两个安装。

Sass、SCSS、Less介绍
Sass (Syntactically Awesome StyleSheets):后缀名为.sass,是由ruby语言编写的一款css预处理语言。
SCSS (Sassy CSS):后缀名为 .scss。SCSS 是 Sass 3 引入新的语法,与原来的语法兼容,只是用{ }替代了原来的缩进。SCSS语法完全兼容 CSS3,并且继承了 Sass 的强大功能。
Less:后缀名为 .less。与Sass类似,也是一款css预处理语言。与Sass不同的是,Less是基于Javascript,是在客户端处理的。Less 既可以在客户端上运行(支持IE 6+,Webkit,Firefox),也可以运行在 Node 服务端。

区别

  • Scss功能较Less强大
    1、scss有变量和作用域
    2、scss有函数的概念
    3、进程控制
    4、数据结构
  • Scss和Less处理机制不一样
    1、前者是通过服务端处理的,后者是通过客户端处理,相比较之下前者解析会比后者快一点。
  • Scss和Less在变量中的唯一区别就是Scss用$,Less用@

安装scss或less即可,只安装一个,如有需要再安装另一个。

  1. 安装scss依赖【优先推荐】
npm add -D scss
  1. 安装less依赖【推荐】
 npm add -D less 
  1. 安装sass 依赖【不推荐】
npm add -D sass

3.4 安装ESLint

ESLint主要用于代码规范、统一代码风格。因为校验严格,所以这个不是必要的功能

  1. 安装ESLint依赖
npm install -D eslint
  1. ESLint的初始化
npm init @eslint/config

执行上述命令后,控制台中会有如下步骤:
1)需要安装 @eslint/create-config,问是否继续: 继续,直接回车;
2)使用ESLint来做什么:选最后一个 To check syntax, find problems, and enforce code style(检查语法、寻找问题、强制代码风格)
3)使用哪种模块化的方式:肯定选 JavaScript modules (import/export) (几乎我参与的 vue 项目都是 ESModule)
4)项目使用什么框架:Vue.js*
5)项目是否使用 TypeScript:Yes
6)项目运行在什么环境:Browser
7)如何定义项目的代码风格:Use a popular style guide 使用流行的风格
8)在流行的风格中选择其中一种:Standard
9)ESLint 配置文件的格式:JavaScript
10)根据上面选择的,提示需要安装一大堆依赖,是否安装?Yes
11)选择使用什么包管理工具安装:npm

接下来耐心等待安装依赖。

依赖安装完毕后,项目的根目录下会自动生成.eslintrc.cjs文件。

  1. 在package.json中配置,对代码进行校验和修复
    scripts下添加"lint:script": "eslint --ext .jsx,.vue,.tsx,.ts,.js --fix",完整代码:

    {
      "name": "vite-vue3-ts-project",
      "private": true,
      "version": "0.0.0",
      "type": "module",
      "scripts": {
        "dev": "vite",
        "build": "vue-tsc && vite build",
        "preview": "vite preview",
        "lint:script": "eslint --ext .jsx,.vue,.tsx,.ts,.js --fix"
      },
      "dependencies": {
        "vue": "^3.3.4"
      },
      "devDependencies": {
        "@typescript-eslint/eslint-plugin": "^6.7.2",
        "@vitejs/plugin-vue": "^4.2.3",
        "eslint": "^8.50.0",
        "eslint-config-standard-with-typescript": "^39.1.0",
        "eslint-plugin-import": "^2.28.1",
        "eslint-plugin-n": "^16.1.0",
        "eslint-plugin-promise": "^6.1.1",
        "eslint-plugin-vue": "^9.17.0",
        "scss": "^0.2.4",
        "typescript": "^5.2.2",
        "vite": "^4.4.5",
        "vue-tsc": "^1.8.5"
      }
    }
    
  2. 在根目录下的.eslintrc.cjs中按如下配置添加

    // eslint配置,用于校验代码
    module.exports = {
        // env指定环境 支持的环境: browser node commonjs es6 es2016~es2022...
        // 环境很多,详情查看文档https://zh-hans.eslint.org/docs/latest/use/configure/language-options
        "env": {
            "browser": true,
            "es2021": true,
            "node": true,
        },
        // 使用插件配置
        "extends": [
            "eslint:recommended",
            "plugin:vue/vue3-essential",
            "plugin:@typescript-eslint/recommended"
        ],
        // "overrides": [
        //     {
        //         "env": {
        //             "node": true
        //         },
        //         "files": [
        //             ".eslintrc.{js,cjs}"
        //         ],
        //         "parserOptions": {
        //             "sourceType": "script"
        //         }
        //     }
        // ],
        // 配置支持的js语言选项
        "parserOptions": {
            "ecmaVersion": "latest",
            "sourceType": "module",
            "parser": "@typescript-eslint/parser"
        },
        // eslint第三方插件配置
        "plugins": [
            "vue",
            "@typescript-eslint"
        ],
        // eslint规则配置,还有很多规则配置项,在官网查看 https://eslint.org/docs/latest/rules/
        "rules": {
            '@typescript-eslint/no-var-requires': 0, //解决报错:Require statement not part of import statement.
            'vue/multi-word-component-names': 'off', //关闭组件命名规则校验
            // => 前后有空格
            "arrow-spacing": [
                2,
                {
                    before: true,
                    after: true,
                },
            ],
            "block-spacing": [2, "always"],
            // 对象字面量项尾是否有逗号
            "comma-dangle": [2, "always-multiline"],
        }
    }
    
  3. WebStorm配置ESLint【可选】
    在这里插入图片描述

3.5 安装Prettier

prettier 是代码格式化工具,用它可以统一代码格式,风格。

  1. 安装Prettier依赖
npm install -D prettier
  1. 依赖安装完毕后,在项目的根目录下创建.prettierrc.cjs配置文件,添加如下配置:
//.prettierrc.cjs
module.exports = {
    printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80
    singleAttributePerLine: false, //每行强制换行,只能使用单个属性
    tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
    useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
    singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号
    semi: false, // 行尾是否添加分号,默认为true
    trailingComma: 'none', //行使用逗号分隔 可选值: es5 none all
    bracketSpacing: true, // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
    endOfLine: 'auto', // 文本文件中的行结束方式 可选值: lf crlf cr auto
    jsxBracketSameLine: false, // 在jsx中把'>' 是否单独放一行
    vueIndentScriptAndStyle: false, // <script>Vue 文件中的代码和标签是否缩进<style>。
    arrowParens: "always", // 箭头函数的括号
}
  1. 同时在根目录创建.prettierignore文件用来忽略不需要Prettier格式化代码的文件
.DS_Store
node_modules
dist
/src/assets/*
dist-ssr

**/*.svg
**/*.sh
  1. (没有冲突时可先不配置)eslintprettier的配置难免会有冲突,如果发生冲突,目前比较成熟的方案是使用以下两个插件:
    • eslint-plugin-prettier: 基于prettier代码风格的eslint规则,即eslint使用pretter规则来格式化代码。
    • eslint-config-prettier: 禁用所有与格式相关的eslint规则,解决prettiereslint规则冲突,确保将其放在extends队列最后,这样它将覆盖其他配置。
npm install -D eslint-config-prettier eslint-plugin-prettier

安装完成后在.eslintrc.cjs文件中extends的最后添加一个配置

    // 使用插件配置
    "extends": [
        "eslint:recommended",
        "plugin:vue/vue3-essential",
        "plugin:@typescript-eslint/recommended",
        "plugin:prettier/recommended" // 新增,必须放在最后面
    ],

3.6 自动导入

  1. 安装
npm install -D unplugin-vue-components unplugin-auto-import
  1. vite.config.ts 引入配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

//1、 导入 path 模块,帮助我们解析路径
import { resolve } from 'path'

//2-1 自动导入vue中hook reactive ref等
import AutoImport from 'unplugin-auto-import/vite'
//2-2 自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        AutoImport({
            //安装两行后你会发现在组件中不用再导入ref,reactive等
            imports: ['vue', 'vue-router'],
            //存放的位置
            dts: "src/auto-import.d.ts",
        }),
        Components({
            // 引入组件的,包括自定义组件,存放的位置
            dts: "src/components.d.ts",
        }),
    ],

    //1、 ↓解析配置
    resolve: {
        // ↓路径别名
        alias: {
            "@": resolve(__dirname, "./src"),
            "_c": resolve(__dirname, "./src/components")
        }
    }
})
  1. components.d.ts配置(仅供参考)
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}

declare module 'vue' {
    export interface GlobalComponents {
        HelloWorld: typeof import('./components/HelloWorld.vue')['default']
        RouterLink: typeof import('vue-router')['RouterLink']
        RouterView: typeof import('vue-router')['RouterView']
    }
}
  1. auto-import.d.ts配置(仅供参考)
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
    const EffectScope: typeof import('vue')['EffectScope']
    const computed: typeof import('vue')['computed']
    const createApp: typeof import('vue')['createApp']
    const customRef: typeof import('vue')['customRef']
    const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
    const defineComponent: typeof import('vue')['defineComponent']
    const effectScope: typeof import('vue')['effectScope']
    const getCurrentInstance: typeof import('vue')['getCurrentInstance']
    const getCurrentScope: typeof import('vue')['getCurrentScope']
    const h: typeof import('vue')['h']
    const inject: typeof import('vue')['inject']
    const isProxy: typeof import('vue')['isProxy']
    const isReactive: typeof import('vue')['isReactive']
    const isReadonly: typeof import('vue')['isReadonly']
    const isRef: typeof import('vue')['isRef']
    const markRaw: typeof import('vue')['markRaw']
    const nextTick: typeof import('vue')['nextTick']
    const onActivated: typeof import('vue')['onActivated']
    const onBeforeMount: typeof import('vue')['onBeforeMount']
    const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
    const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
    const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
    const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
    const onDeactivated: typeof import('vue')['onDeactivated']
    const onErrorCaptured: typeof import('vue')['onErrorCaptured']
    const onMounted: typeof import('vue')['onMounted']
    const onRenderTracked: typeof import('vue')['onRenderTracked']
    const onRenderTriggered: typeof import('vue')['onRenderTriggered']
    const onScopeDispose: typeof import('vue')['onScopeDispose']
    const onServerPrefetch: typeof import('vue')['onServerPrefetch']
    const onUnmounted: typeof import('vue')['onUnmounted']
    const onUpdated: typeof import('vue')['onUpdated']
    const provide: typeof import('vue')['provide']
    const reactive: typeof import('vue')['reactive']
    const readonly: typeof import('vue')['readonly']
    const ref: typeof import('vue')['ref']
    const resolveComponent: typeof import('vue')['resolveComponent']
    const shallowReactive: typeof import('vue')['shallowReactive']
    const shallowReadonly: typeof import('vue')['shallowReadonly']
    const shallowRef: typeof import('vue')['shallowRef']
    const toRaw: typeof import('vue')['toRaw']
    const toRef: typeof import('vue')['toRef']
    const toRefs: typeof import('vue')['toRefs']
    const toValue: typeof import('vue')['toValue']
    const triggerRef: typeof import('vue')['triggerRef']
    const unref: typeof import('vue')['unref']
    const useAttrs: typeof import('vue')['useAttrs']
    const useCssModule: typeof import('vue')['useCssModule']
    const useCssVars: typeof import('vue')['useCssVars']
    const useLink: typeof import('vue-router')['useLink']
    const useRoute: typeof import('vue-router')['useRoute']
    const useRouter: typeof import('vue-router')['useRouter']
    const useSlots: typeof import('vue')['useSlots']
    const watch: typeof import('vue')['watch']
    const watchEffect: typeof import('vue')['watchEffect']
    const watchPostEffect: typeof import('vue')['watchPostEffect']
    const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
    // @ts-ignore
    export type {
        Component,
        ComponentPublicInstance,
        ComputedRef,
        InjectionKey,
        PropType,
        Ref,
        VNode,
        WritableComputedRef
    } from 'vue'
}

3.7 安装配置router

  1. npm方式
npm install vue-router@4
  1. 配置步骤

    1. 创建测试页面
      • views/about/index.vue
    <template>
        <div>
            <h1>About Page</h1>
        </div>
    </template>
    
    <script>
    export default {
        name: "index"
    }
    </script>
    
    <style scoped>
    
    </style>
    
    • views/home/index.vue
    <template>
        <div>
            <h1>Home Page</h1>
        </div>
    </template>
    
    <script>
    export default {
        name: "index"
    }
    </script>
    
    <style scoped>
    
    </style>
    
    1. 配置路由,在src下创建一个router文件夹,再创建一个index.ts文件
      注意:必须要有path"/"的路由,否则浏览器控制台报No match found for location with path "/"
    import { createRouter, createWebHistory } from "vue-router"
    
    const routes = [
        {
            path: '/',
            redirect: 'index',
        },
        {
            path: '/index',
            name: 'Home',
            component: () => import('@/views/home/index.vue')
        },
        {
            path: '/about',
            name: 'About',
            //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
            component: () => import('@/views/about/index.vue')
        },
        //{
        //配置404页面
        //path: '/:catchAll(.*)',
        //name: '404',
        //component: () => import(''),
        //}
    ]
    // 路由
    const router = createRouter({
        history: createWebHistory(),
        routes
    })
    // 导出
    export default router
    
  2. 在src的main.ts文件引入。

    import { createApp } from 'vue'
    import './style.css'
    import App from './App.vue'
    
    //1、route
    import router from '@/router/index'
    
    const app = createApp(App)
    
    //1、route
    app.use(router)
    app.mount('#app')
    
  3. App.vue使用路由

    <script setup lang="ts">
    </script>
    
    <template>
      <!--    路由跳转-->
        <router-link to="/">首页</router-link>
        <br>
        <router-link to="/about">关于</router-link>
        <router-view></router-view>
    </template>
    
    <style scoped>
    
    </style>
    

3.8 安装Pinia

参考1:Vue3 Vite3 状态管理 pinia 基本使用、持久化、在路由守卫中的使用

因为是vue3+ts,安装Pinia更好点,vuex拥抱ts没有Pinia好。

Pinia介绍
参考:什么是Pinia?
Pinia和Vuex一样都是是vue的全局状态管理器。其实Pinia就是Vuex5,只不过为了尊重原作者的贡献就沿用了这个看起来很甜的名字Pinia。


3.8.1 Pinia的使用

  1. npm方式安装
    npm install pinia
    
  2. 在src下创建一个store文件夹,再创建一个index.ts文件

其它名也可以,因为pinia它有一个根文件,会把createPinia第一个参数当id值,相当于vuex中的module自动引入,也会在Vue.js devtools插件中以第一个参数名展示(下面展示)
注意createPinia第一个参数很重要,而且是唯一值。它的命名在devtools插件能方便找到这个文件的数据,方便调试。

import { createPinia } from 'pinia'

const pinia = createPinia()
export default pinia
  1. srcmain.ts引入
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

//1、route
import router from '@/router/index'

//2、pinia
import pinia from '@/store'

const app = createApp(App)

//1、route
app.use(router)
//2、pinia
app.use(pinia)
app.mount('#app')
  1. store文件夹下创建modules目录,存储每个模块的状态,新建demo.ts。这里使用最新的Composition APIsetup的方式来定义状态。
import { defineStore } from 'pinia'
import { ref } from 'vue'

const useDemoStore = defineStore('demo', () => {
    const counter = ref(0)
    const increment = () => {
        counter.value++
    }
    return {
        counter,
        increment
    }
})
export default useDemoStore
  1. 使用pinia
    在路由示例的about.vue页面使用!
    <template>
        <div>
            <h1>About Page</h1>
            <h3>counter: {{ counter }}</h3>
            <button @click="add">计数</button>
        </div>
    </template>
    
    <script setup lang="ts">
    import useDemoStore from '@/store/modules/demo'
    import { storeToRefs } from 'pinia'
    
    const demoStore = useDemoStore()
    const {counter} = storeToRefs(demoStore)
    const add = () => {
        demoStore.increment()
    }
    </script>
    
    <style scoped>
    button {
        color: cornflowerblue;
        font-size: 30px;
    }
    </style>
    

3.8.2 Pinia状态持久化

3.7.1中,假设计数器加到5,如果刷新浏览器,counter的值又会被初始化为0。这是因为状态是存储在浏览器内存中的,刷新浏览器后,重新加载页面时会重新初始化vuepinia,而pinia中状态的值仅在内存中存在,而刷新导致浏览器存储中的数据没了,所以counter的值就被初始化为0

要解决这个问题非常简单,在状态改变时将其同步到浏览器的存储中,如cookielocalStoragesessionStorage。每次初始化状态时从存储中去获取初始值即可。

使用pinia的插件pinia-plugin-persistedstate来实现。

  1. 安装依赖
npm install pinia-plugin-persistedstate
  1. 引入该插件,在src的store文件夹下修改index.ts文件:
import { createPinia } from 'pinia'

import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()

pinia.use(piniaPluginPersistedstate)
export default pinia
  1. 设置persist持久化
    在需要持久化状态的模块中设置persist。假设demo模块需要对状态需要持久化,defineStore第一个参数定义唯一的模块名,第二个参数传递setup,其实还有第三个参数options,在options中便可开启持久化:

修改store/modules/demo.ts

import { defineStore } from 'pinia'
import { ref } from 'vue'

const useDemoStore = defineStore('demo', () => {
    const counter = ref(0)
    const increment = () => {
        counter.value++
    }
    return {
        counter,
        increment
    }
}, {
    persist: true
})
export default useDemoStore

会将状态缓存在localStorage中。
4. 如果需要将其存储在sessionStorage中,就需要设置persist的值为一个对象:

import { defineStore } from 'pinia'
import { ref } from 'vue'

const useDemoStore = defineStore('demo', () => {
    const counter = ref(0)
    const increment = () => {
        counter.value++
    }
    return {
        counter,
        increment
    }
}, {
    persist: {
        key: 'aaa',
        storage: sessionStorage
    }
})
export default useDemoStore

3.9 安装配置axios

  1. npm方式安装
npm install axios
  1. 封装request
    src下创建一个utils文件夹,添加request.ts文件
import axios from 'axios'
// 创建axios实例
const request = axios.create({
    baseURL: '',// 所有的请求地址前缀部分(没有后端请求不用写)
    timeout: 80000, // 请求超时时间(毫秒)
    withCredentials: true,// 异步请求携带cookie
    // headers: {
    // 设置后端需要的传参类型
    // 'Content-Type': 'application/json',
    // 'token': x-auth-token',//一开始就要token
    // 'X-Requested-With': 'XMLHttpRequest',
    // },
})

// request拦截器
request.interceptors.request.use(
    config => {
        // 如果你要去localStor获取token
        let token = localStorage.getItem("x-auth-token");
        if (token) {
            //添加请求头
            config.headers["Authorization"] = "Bearer " + token
        }
        return config
    },
    error => {
        // 对请求错误做些什么
        Promise.reject(error)
    }
)

// response 拦截器
request.interceptors.response.use(
    response => {
        // 对响应数据做点什么
        return response.data
    },
    error => {
        // 对响应错误做点什么
        return Promise.reject(error)
    }
)
export default request
  1. 创建调用的接口
    src下创建一个api文件夹,然后再在api下创建login文件夹,添加login.ts文件

定义接口格式:
export const 自定义接口名 = (形参:请求类型):返回类型 => instance.方法(路径,后端要的参数);

import instance from "@/utils/request";

//一般情况下,接口类型会放到一个文件
// 下面两个TS接口,表示要传的参数
interface ReqLogin {
    name: string
    paw: string
}

interface ReqStatus {
    id: string
    navStatus: string
}


// Res是返回的参数,T是泛型,需要自己定义,返回对数统一管理***
type Res<T> = Promise<ItypeAPI<T>>;
// 一般情况下响应数据返回的这三个参数,
// 但不排除后端返回其它的可能性,
interface ItypeAPI<T> {
    data: T,//请求的数据,用泛型
    msg: string | null // 返回状态码的信息,如请求成功等
    code: number //返回后端自定义的200,404,500这种状态码
}


// post请求 ,没参数
export const LogoutAPI = (): Res<null> => instance.post("/admin/logout");

// post请求,有参数,如传用户名和密码
export const loginAPI = (data: ReqLogin): Res<string> =>
    instance.post("/admin/login", data);

// post请求 ,没参数,但要路径传参
export const StatusAPI = (data: ReqStatus): Res<null> =>
    instance.post(`/productCategory?ids=${data.id}&navStatus=${data.navStatus}`);


//  get请求,没参数,
export const FlashSessionListApi = (): Res<null> =>
    instance.get("/flashSession/list");

// get请求,有参数,路径也要传参  (也可能直接在这写类型,不过不建议,大点的项目会维护一麻烦)
export const ProductCategoryApi = (params: { parentId: number }): Res<any> =>
    instance.get(`/productCategory/list/${params.parentId}`, {params});

// get请求,有参数,(如果你不会写类型也可以使用any,不过不建议,因为用了之后 和没写TS一样)
export const AdminListAPI = (params: any): Res<any> => instance.get("/admin/list", {params});
  1. 在要请求的组件上使用
    方式1:使用.then
<script setup lang="ts">
import {loginAPI} from "@/api/login";

const login= () => {
    loginAPI({
        ...val,
    }).then((res) => {
        console.log('***',res );
        let { list, pageNum, pageSize, total } = res.data
    })

};
</script>

方式2:直接使用(和vue2cretae上用一样,setup自带asyncawait在顶层可以直接使用)

<script setup lang="ts">
import { loginAPI} from "@/api/login";
    //直接使用,一般用在进入页面入请求数据的接口
    let res = await loginAPI()
    console.log( "***" ,res);
}
</script>

方式3:使用async/await,(setup虽然自带async,但单独用await只能在顶层使用,如果在函数下还是要async/await一起写)

<script setup lang="ts">
import { loginAPI} from "@/api/login";
 
const search = async(val: IUseTableParam) => {
    let res = await loginAPI({
        ...val,
    })
    console.log( "***" ,res);
    let { list, pageNum, pageSize, total } = res.data
    console.log(list, pageNum, pageSize, total);
}
</script>
  1. 代理

    需要代理才写

src目录的utils下的request.ts添加文件

const request = axios.create({
    //这时你要代理
    //填写后端统一的前缀,
    //如:123.xx.xx.xx:456/api/...
    //这个/api是每一个接口都有的,就写它
    //如果没有,也写,下面会讲区别
    baseURL: '/api',
})

完整代码:

import axios from 'axios'
// 创建axios实例
const request = axios.create({
    // baseURL: '',// 所有的请求地址前缀部分(没有后端请求不用写)

    //这时你要代理
    //填写后端统一的前缀,
    //如:123.xx.xx.xx:456/api/...
    //这个/api是每一个接口都有的,就写它
    //如果没有,也写,下面会讲区别
    baseURL: '/api',
    timeout: 80000, // 请求超时时间(毫秒)
    withCredentials: true,// 异步请求携带cookie
    // headers: {
    // 设置后端需要的传参类型
    // 'Content-Type': 'application/json',
    // 'token': x-auth-token',//一开始就要token
    // 'X-Requested-With': 'XMLHttpRequest',
    // },
})

// request拦截器
request.interceptors.request.use(
    config => {
        // 如果你要去localStor获取token
        let token = localStorage.getItem("x-auth-token");
        if (token) {
            //添加请求头
            config.headers["Authorization"] = "Bearer " + token
        }
        return config
    },
    error => {
        // 对请求错误做些什么
        Promise.reject(error)
    }
)

// response 拦截器
request.interceptors.response.use(
    response => {
        // 对响应数据做点什么
        return response.data
    },
    error => {
        // 对响应错误做点什么
        return Promise.reject(error)
    }
)
export default request

vite.config.ts 文件:只需添加server部分即可。

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

//1、 导入 path 模块,帮助我们解析路径
import { resolve } from 'path'

//2-1 自动导入vue中hook reactive ref等
import AutoImport from 'unplugin-auto-import/vite'
//2-2 自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        AutoImport({
            //安装两行后你会发现在组件中不用再导入ref,reactive等
            imports: ['vue', 'vue-router'],
            //存放的位置
            dts: "src/auto-import.d.ts",
        }),
        Components({
            // 引入组件的,包括自定义组件,存放的位置
            dts: "src/components.d.ts",
        }),
    ],

    //1、 ↓解析配置
    resolve: {
        // ↓路径别名
        alias: {
            "@": resolve(__dirname, "./src"),
            "_c": resolve(__dirname, "./src/components")
        }
    },

    //代理
    server: {
        proxy: {
            '/api': { // 匹配请求路径,
                target: '你要代理的地址', // 代理的目标地址
                // 开发模式,默认的127.0.0.1,开启后代理服务会把origin修改为目标地址
                changeOrigin: true,
                // secure: true, // 是否https接口
                // ws: true, // 是否代理websockets

                // 路径重写,**** 如果你的后端有统一前缀(如:/api),就不开启;没有就开启
                //简单来说,就是是否改路径 加某些东西
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
})

3.10 自定义组件名setup语法糖

在 vue 3.2.34 或以上的版本中,使用 <script setup> 的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明。也就是说,除非你想换名,并且又不想写两个 script 标签,就可以通过下面的链接去做。

  1. 安装vite-plugin-vue-setup-extend
npm install -D vite-plugin-vue-setup-extend
  1. 配置vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

//1、 导入 path 模块,帮助我们解析路径
import { resolve } from 'path'

//2-1 自动导入vue中hook reactive ref等
import AutoImport from 'unplugin-auto-import/vite'
//2-2 自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite'

//3、vue3语法糖
import VueSetupExtend from 'vite-plugin-vue-setup-extend'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        AutoImport({
            //安装两行后你会发现在组件中不用再导入ref,reactive等
            imports: ['vue', 'vue-router'],
            //存放的位置
            dts: "src/auto-import.d.ts",
        }),
        Components({
            // 引入组件的,包括自定义组件,存放的位置
            dts: "src/components.d.ts",
        }),
        VueSetupExtend(),
    ],

    //1、 ↓解析配置
    resolve: {
        // ↓路径别名
        alias: {
            "@": resolve(__dirname, "./src"),
            "_c": resolve(__dirname, "./src/components")
        }
    },

    //代理
    server: {
        proxy: {
            '/api': { // 匹配请求路径,
                target: '你要代理的地址', // 代理的目标地址
                // 开发模式,默认的127.0.0.1,开启后代理服务会把origin修改为目标地址
                changeOrigin: true,
                // secure: true, // 是否https接口
                // ws: true, // 是否代理websockets

                // 路径重写,**** 如果你的后端有统一前缀(如:/api),就不开启;没有就开启
                //简单来说,就是是否改路径 加某些东西
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
})
  1. 使用
<script setup lang="ts" name="home">
 
</script>

3.11 安装element-plus组件库

element-plusAnt Design Vue都是组件库,可以只安装其中一个,也可以两个都装,相辅相成。

  1. 安装element-plus组件库
    NPM方式
npm install element-plus --save
  1. 安装element-icon图标
npm install @element-plus/icons-vue
  1. main.ts引入
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

//1、route
import router from '@/router/index'

//2、pinia
import pinia from '@/store'

//3、element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)

//1、route
app.use(router)
//2、pinia
app.use(pinia)
//3、element-plus
app.use(ElementPlus)
app.mount('#app')
  1. 使用
    .vue页面引入所需组件即可。

  2. ElMessageElLoading 找不到的问题【没有报错时可不配置】

如果项目使用时出现问题找不到模块element-plus或其相应的类型声明的问题需要。

  • src根目录创建Element-plus.d.ts文件
//文件内容
export {}
declare global {
    const ElMessage: typeof import('element-plus')['ElMessage']
    const ElLoading: typeof import('element-plus')['ElLoading']
}
  • 然后在tsconfig.json文件添加一行代码
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    //添加这行
    "Element-plus.d.ts"
  ],

完整代码:

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": [
      "ES2020",
      "DOM",
      "DOM.Iterable"
    ],
    "skipLibCheck": true,
    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    // 配置@别名 start
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ],
      "_c/*": [
        "src/components/*"
      ]
    }
    // 配置@别名 end
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    //添加这行
    "Element-plus.d.ts"
  ],
  "references": [
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

3.12 安装与使用Echarts

参考:vue3 + ts 在 setup 下使用Echarts

  1. 安装Echarts
npm install echarts --save
  1. main.ts引入
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

//1、route
import router from '@/router/index'

//2、pinia
import pinia from '@/store'

//3、element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

//4、引入echarts
import * as echarts from 'echarts'

const app = createApp(App)

//1、route
app.use(router)
//2、pinia
app.use(pinia)
//3、element-plus
app.use(ElementPlus)
//4、放入全局
app.config.globalProperties.$echarts = echarts
app.mount('#app')
  1. .vue使用
    • html部分
    <template>
        <div id='myChart' style='width:300px; height:300px;position: absolute;'></div>
    </template>
    
    • js代码部分
    <script>
    import {defineComponent, toRefs, reactive, onMounted} from 'vue'
    import * as echarts from 'echarts'
    
    export default defineComponent({
        name: 'Histogram',
        setup() {
            const state = reactive({
                option: {
                    grid: {
                        top: '4%',
                        left: '2%',
                        right: '4%',
                        bottom: '0%',
                        containLabel: true,
                    },
                    xAxis: [
                        {
                            type: 'category',
                            data: ["芳草地国际", "实验小学", "白家庄小学", "外国语小学", "师范学校附属", "望京东园"],
                            axisTick: {
                                alignWithLabel: true,
                            },
                        },
                    ],
                    yAxis: [
                        {
                            type: 'value',
                        },
                    ],
                    series: [
                        {
                            name: '学校',
                            type: 'bar',
                            barWidth: '40%',
                            data: [260, 680, 360, 460, 150, 320],
                        },
                    ],
                },
            })
            const initeCharts = () => {
                let myChart = echarts.init(document.getElementById('myChart'))
                // 绘制图表
                myChart.setOption(state.option)
            }
    
            onMounted(() => {
                initeCharts()
            })
    
            return {
                ...toRefs(state),
            }
        },
    })
    </script>
    

完整代码:

<template>
    <div id='myChart' style='width:300px; height:300px;position: absolute;'></div>
</template>

<script>
import {defineComponent, toRefs, reactive, onMounted} from 'vue'
import * as echarts from 'echarts'

export default defineComponent({
    name: 'Histogram',
    setup() {
        const state = reactive({
            option: {
                grid: {
                    top: '4%',
                    left: '2%',
                    right: '4%',
                    bottom: '0%',
                    containLabel: true,
                },
                xAxis: [
                    {
                        type: 'category',
                        data: ["芳草地国际", "实验小学", "白家庄小学", "外国语小学", "师范学校附属", "望京东园"],
                        axisTick: {
                            alignWithLabel: true,
                        },
                    },
                ],
                yAxis: [
                    {
                        type: 'value',
                    },
                ],
                series: [
                    {
                        name: '学校',
                        type: 'bar',
                        barWidth: '40%',
                        data: [260, 680, 360, 460, 150, 320],
                    },
                ],
            },
        })
        const initeCharts = () => {
            let myChart = echarts.init(document.getElementById('myChart'))
            // 绘制图表
            myChart.setOption(state.option)
        }

        onMounted(() => {
            initeCharts()
        })

        return {
            ...toRefs(state),
        }
    },
})
</script>

<style scoped>

</style>

3.13 安装Ant Design Vue组件库【可选】

  1. 安装ant-design-vue
npm install ant-design-vue --save
  1. 安装ant-design图标
npm install --save @ant-design/icons-vue
  1. main.ts引入
import {createApp} from 'vue'
import '@/style.css'
import App from '@/App.vue'

//1、routes
import router from "@/router/index"
//2、pinia
import {createPinia} from 'pinia'

//3、element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

//4、ant-design-vue
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'

const app = createApp(App)
const pinia = createPinia()

//1、routes
app.use(router)
//2、pinia
app.use(pinia)
//3、element-plus
app.use(ElementPlus)
//4、ant-design-vue
app.use(Antd)
app.mount('#app')
  1. 使用
    直接使用即可。

4 源码

本次示例代码已提交到码云上:https://gitee.com/XiMuQi/vite-vue3-ts-project

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值