Vue.js3 + Vite + TypeScript 开发项目

安装Vite

npm init vite@latest

vite创建.png

初始目录结构.png

安装eslint

  • npm install eslint --save-dev

  • npx eslint --init (初始化eslint配置)

  • 添加 npm script 验证脚本

"scripts": {
    ...
  "lint": "eslint src/**/*.{js,jsx,vue,ts,tsx} --fix",
}
规则.png

替换为vue3规则.png

编辑器集成eslint

  • 禁用Vetur
  • 安装eslint插件
  • 安装Volar插件

配置 git commit hook

npx mrm@2 lint-staged

  • https://github.com/okonet/lint-staged
    在commit之前 对代码进行校验
    安装后.png
"lint-staged": {
    "*.{js,jsx,vue,ts,tsx}": [
      "npm run lint",
      // "git add" 之前的版本需要手动把 lint 过程中修改的代码手动 add,新版本不需要了
    ]
  }

vite-plugin-eslint

npm install vite-plugin-eslint --save-dev

  • vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintplugin from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(),eslintplugin({'配置参数'})]
})

commit 提交规范

Commit message 和 Change log 编写指南
Install commitlint

提交type.png

Vue3 ts支持

  • vue文件添加ts声明

vue3中ts相关写法

Vue3 中的

单独一个组件文件 text.tsx

//函数式组件
export default () => {
  return (
    

text函数式组件

) } //需要有状态的组件 options API import { defineComponent } from '@vue/runtime-core' export default defineComponent({ props:{ msg:{ type:String } }, render(){ return (
{ this.msg }
) } }) //需要有状态的组件 组合式 API import { defineComponent,ref } from '@vue/runtime-core' interface PropsType { msg:string } export default defineComponent({ props:{ msg:{ type:String } }, setup(){ const count = ref (0) return (props:PropsType ) => (

{props.msg}

{count}

) } })

初始化VueRouter

  • 安装vue-router

npm install vue-router@4

// src\router\index.ts
import { createRouter, RouteRecordRaw, createWebHashHistory } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    component: () => import('../views/home/index.vue')
  },
  {
    path: '/login',
    component: () => import('../views/login/index.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
// src\main.ts
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')

初始化 Vuex

  • 安装Vuex

npm install vuex@next --save

// src\store\index.ts
import { createStore } from 'vuex'

const store = createStore({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {}
})

export default store
// src\main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App)
  .use(router)
  .use(store)
  .mount('#app')
vuex.png

usestore-组合式函数类型声明

结合ts优化后

//store/index.ts
import { createStore, useStore as baseUseStore, Store } from 'vuex'
import { InjectionKey } from 'vue'

export interface State {
  count: number
}

// 定义 injection key
export const key: InjectionKey> = Symbol('store')

export const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})

// 定义自己的 `useStore` 组合式函数 //调用该 useStore 可以推断出state属性及类型
export function useStore() {
  return baseUseStore(key)
}

export default store
// vuex.d.ts
import { ComponentCustomProperties } from 'vue'
import { Store } from 'vuex'
import { State } from './store/index'

declare module '@vue/runtime-core' {
  // 声明自己的 store state
  // interface State {
  //   count: number
  // }

  // 为 `this.$store` 提供类型声明
  interface ComponentCustomProperties {
    $store: Store
  }
}

配置模块路径别名

vite不自带@等路径别名

import xxx from '@/views/xxx.vue'  //不支持src别名@符  所以要手动配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 注意:在 ts 模块中加载 node 核心模块需要安装 node 的类型补充模块:npm i -D @types/node
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  ...
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }
})
// tsconfig.json   
//所有以@开头的都指向src
{
  "compilerOptions": {
    ...
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  ...
}

使用

// js
import xxx from '@/api/xxx.ts'

// html


// css
@import url("@/styles/index.scss");
background: url("@/assets/logo.png");

CSS样式管理

vite css配置 文档
Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:

# .scss and .sass
npm install -D sass

# .less
npm install -D less

# .styl and .stylus
npm install -D stylus

如果是用的是单文件组件,可以通过

要想在全局单文件中不用单独引入就可以使用scss全局变量 需要配置使用全局样式
配置使用全局样式变量
css-preprocessoroptions
vite.config.ts

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueJsx({
      // 配置选项
    })
  ],
  resolve: {
    alias: {
      '@': path.join(__dirname, 'src')//绝对路径
    }
  },
  css: {
    preprocessorOptions: {
      // 给 sass-loader 传递选项
      sass: {
        // @/ 是 src/ 的别名
        // 所以这里假设你有 `src/variables.sass` 这个文件
        // 注意:在 sass-loader v8 中,这个选项名是 "prependData"
        additionalData: `@import "@/styles/variables.scss"`
      },
      // 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
      // 因为 `scss` 语法在内部也是由 sass-loader 处理的
      // 但是在配置 `prependData` 选项的时候
      // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
      // 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
      scss: {
        additionalData: `@import "~@/variables.scss";`
      },
      // 给 less-loader 传递 Less.js 相关选项
      less: {
        // http://lesscss.org/usage/#less-options-strict-units `Global Variables`
        // `primary` is global variables fields name
        globalVars: {
          primary: '#fff'
        }
      }
    }
  }
})

自动注册全局组件

glob-impor
全局组件放在 components 目录下

- components
    + foo
    + index.vue
    + index.ts
  + bar
    + index.vue
    + index.ts
- main.ts
// main.ts

const app = createApp(App)

const modules = import.meta.globEager('./components/**/index.ts')

for (const path in modules) {
  app.use(modules[path].default)
}
// components/foo/index.ts

import { App } from '@vue/runtime-dom'
import Component from './index.vue'

export default {
  install (app: App) {
    app.component('Foo', Component)
  }
}
// components/bar/index.ts

import { App } from '@vue/runtime-dom'
import Component from './index.vue'

export default {
  install (app: App) {
    app.component('Bar', Component)
  }
}

服务端交互

**基于axios封装请求模块

  • 安装axios

npm i axios
基础配置

//src/utils/request.ts
import axios from 'axios'

const request = axios.create({
  baseURL: '' //基础请求路径
})

// 请求拦截器
request.interceptors.request.use(
  config => {
    // 统一设置用户身份 Token
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  response => {
    // 统一处理响应错误,例如 token 无效、服务端异常等
    return response
  },
  err => {
    return Promise.reject(err)
  }
)

export default request
/**
 * 公共基础接口封装
 */
import request from '@/utils/request'

export const getLoginInfo = () => {
  return request({
    method: 'GET',
    url: '/login/info'
  })
}
/**
 * 组件中使用
 */
import { getLoginInfo } from '@/api/common'
import { onMounted } from '@vue/runtime-core'

onMounted(() => {
  getLoginInfo().then(res => {
    console.log(res)
  })
})

多环境 baseURL

环境变量和模式

# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=http://a.com
# .env.production

# 生产模式下加载的环境变量
VITE_API_BASEURL=http://b.com
// src\utils\request.ts

const request = axios.create({
  // localhost:8080/xxx
  // abc.com/xxx
  // test.com/xxx
  baseURL: import.meta.env.VITE_API_BASEURL
})
//env.d.ts中对类型声明
/// 

declare module '*.vue' {
  import { DefineComponent } from 'vue'
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>
  export default component
}

interface ImportMetaEnv {
  VITE_API_BASEURL: string
  // 更多环境变量...
}

跨域问题

推荐方案

  • 开发环境
    • 在服务端配置 CORS。
    • 配置开发服务器代理,比如 vite-server.proxy。
  • 生产环境
    • 在服务端配置 CORS。
    • 配置生产服务器代理,比如 nginx。

CORS
CORS 全称为 Cross Origin Resource Sharing(跨域资源共享)。这种方案对于前端来说没有什么工作量,和正常发送请求写法上没有任何区别,工作量基本都在后端(其实也没啥工作量,就是配置一些 HTTP 协议)。

  • 跨源资源共享(CORS)
  • 跨域资源共享 CORS 详解

服务器代理
可能有些后端开发人员觉得配置 CORS 麻烦不想搞,那纯前端也是有解决方案的。

在开发模式下可以下使用开发服务器的 proxy 功能,比如 vite - server.proxy。

但这种方法在生产环境是不能使用的。在生产环境中需要配置生产服务器(比如 nginx、Apache 等)进行反向代理。在本地服务和生产服务配置代理的原理都是一样的,通过搭建一个中转服务器来转发请求规避跨域的问题。


图片.png
//vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      // 字符串简写写法
      '/foo': 'http://localhost:4567',
      // 选项写法
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      },
      // 正则表达式写法
      '^/fallback/.*': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/fallback/, '')
      },
      // 使用 proxy 实例
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        configure: (proxy, options) => {
          // proxy 是 'http-proxy' 的实例
        }
      }
    }
  }
})

初始化 Element Plus

npm install element-plus --save
Element Plus快速开始

你可能感兴趣的:(Vue.js3 + Vite + TypeScript 开发项目)