vite + vue3 + ts 项目搭建及项目框架搭建
vite+vue3+ts创建Vite-Vue项目项目初始化完善项目结构代码规范与 [ESLint](https://eslint.org/docs/user-guide/getting-started)ESLint下载 并运行eslint文件配置命令行配置在VSCode 编辑器中显示eslint错误配置创建Vite-Vue项目我这里用的npm其他项目初始化// 我用的npmnpm init vit
·
vite+vue3+ts
创建Vite-Vue项目
- 我这里用的npm 其他
项目初始化
// 我用的npm
npm init vite@latest
- 安装如下流程进行安装
Need to install the following packages:
create-vite@latest
Ok to proceed? (y) y
√ Project name: ... todos-list
√ Select a framework: » vue
√ Select a variant: » vue-ts
Scaffolding project in D:\Learning\todos-list...
Done. Now run:
cd todos-list
npm install
npm run dev
完善项目结构
- 在scr目录下新增一些文件结构
文件名 | 用途 |
---|---|
api | 存放请求相关文件 |
layout | 布局 |
plugins | 插件 |
composables | 组合式 API 抽离方法 |
router | 路由 |
store | 仓储 |
styles | 公共样式 |
utils | 工具函数 |
views | 路由页面 |
代码规范与 ESLint
ESLint下载 并运行
npm install eslint -D
npx eslint --init
- 根据向导安装eslint相关包
PS D:\Learning\todos-list> npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
@eslint/create-config
Ok to proceed? (y) y
? How would you like to use ESLint? ...
To check syntax only
To check syntax and find problems
√ How would you like to use ESLint? · style
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · No / Yes
√ Where does your code run? · browser
√ How would you like to define a style for your project? · guide
√ Which style guide do you want to follow? · standard
√ What format do you want your config file to be in? · JavaScript
Checking peerDependencies of eslint-config-standard@latest
√ The style guide "standard" requires eslint@^7.12.1. You are currently using eslint@8.11.0.
Do you want to downgrade? · No / Yes
The config that you've selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest eslint-config-standard@latest eslint@^7.12.1 eslint-plugin-import@^2.22.1 eslint-plugin-node@^11.1.0 eslint-plugin-promise@^4.2.1 || ^5.0.0 @typescript-eslint/parser@latest
√ Would you like to install them now with npm? · No / Yes
Installing eslint-plugin-vue@latest, @typescript-eslint/eslint-plugin@latest, eslint-config-standard@latest, eslint@^7.12.1, eslint-plugin-import@^2.22.1, eslint-plugin-node@^11.1.0, eslint-plugin-promise@^4.2.1 || ^5.0.0, @typescript-eslint/parser@latest
added 124 packages, removed 1 package, and changed 8 packages in 18s
Successfully created .eslintrc.js file in D:\Learning\todos-list
eslint文件配置
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
// 'plugin:vue/essential', vue2的规则
// 在 node_modules/eslint-plugin-vue/lib/conmfigs 文件夹下
'plugin:vue/vue3-strongly-recommended', // vue3
'standard'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: [
'vue',
'@typescript-eslint'
],
rules: {
}
}
命令行配置
"scripts": {
"lint":"eslint ./src/**/*.{js,jsx,vue,ts,tsx} --fix"
},
在VSCode 编辑器中显示eslint错误
- 卸载/禁用 Vuter
- 安装 ESLint 插件
- 默认查找项目中的验证规则,并给出提示
- 安装 Volar 插件
配置
- 打开设置,扩展,选取eslint, 启用格式化工具选项
- 鼠标右键,选择格式化文档的方式,设置默认格式化方式,ESLint
- 快捷键: Shift + Alt + F
配置git commit hook
下载 lint-staged
npx mrm@2 lint-staged
- husky 钩子脚本工具
- lint-staged 验证
配置
- package.json 文件中修改配置(用于本地git提交的校验)
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"npm run lint",
"git add"
]
}
开发构建中进行代码规范校验
vite-plugin-eslint 的下载
- 我这里用的 vite-plugin-eslint,
npm install vite-plugin-eslint --save-dev
配置
- vite.comfig.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({
// 配置选项
cache: false // 缓存,默认开启
})
]
})
初始化 vueRouter
安装 vue-router
npm i vue-router@4
初始化路由实例
- 在router文件夹下创建index.ts文件
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [{
path: '/',
name: 'Home',
component: () => import('../views/home/IndexHome.vue')
}]
const router = createRouter({
history: createWebHashHistory(), // 路由模式
routes
})
export default router
- 挂载router实例,及配置路由出口
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App)
.use(router)
.mount('#app')
// App.vue
<template>
<router-view />
</template>
初始化 Vuex
安装 Vuex
npm install vuex@next --save
配置Store
// index.ts 文件
import { createStore, Store } from 'vuex'
import { InjectionKey } from 'vue'
export interface State {
count: number,
foo: string
}
// 定义 injection key
export const key: InjectionKey<Store<State>> = Symbol('')
// 创建store实例
export const store = createStore<State>({
state () {
return {
count: 0,
foo: 'Hi'
}
},
mutations: {
increment (state) {
state.count++
}
}
})
- vuex.d.ts 文件
/* eslint-disable no-unused-vars */
// 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<State>
}
}
- main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { store, key } from './store'
createApp(App)
.use(router)
.use(store, key)
.mount('#app')
- 在使用以上配置,使用useStore时,每次都需要导入相关配置,较为麻烦
- 简化 useStore 用法
import { createStore, Store, useStore as baseUseStore } from 'vuex'
import { InjectionKey } from 'vue'
export interface State {
count: number,
foo: string
}
// 定义 injection key
export const key: InjectionKey<Store<State>> = Symbol('')
// 创建store实例
export const store = createStore<State>({
state () {
return {
count: 0,
foo: 'Hi'
}
},
mutations: {
increment (state) {
state.count++
}
}
})
// 定义自己的useStore组合式函数
export function useStore () {
return baseUseStore(key)
}
模块路径别名
配置
- vite.config.ts
import path from 'path'
resolve: {
alias: {
// '@':'绝对路径', 若有需要,自行配置其他
'@': path.join(__dirname, 'src')
}
}
- tsconfig.json
{
"compilerOptions": {
// 路径配置
"paths": {
"@/*": [
"./src/*"
]
}
}
}
path引入时的报错解决
- npm i @types/node 下载node相关的类型声明
- 模块 ““path”” 只能在使用 “allowSyntheticDefaultImports” 标志时进行默认导入
- tsconfig.node.josn配置
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
CSS 样式管理
- vite对css的支持
- 支持预处理器,这里以sass为例
下载相关预处理器
npm i -D sass
配置
- 在 styles 文件下搭建样式目录结构
- index.scss 组织统一导出
- variables.scss 全局 Sass变量
- minxin.scss 全局mixin
- common.scss 全局公共样式
- transition.scss 全局过渡动画样式
- index.scss 文件
@import './common.scss';
@import './mixin.scss';
@import './transitiono.scss';
@import './variables.scss';
- main.ts 文件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { store, key } from './store'
// 加载全局样式
import './styles/index.scss'
createApp(App)
.use(router)
.use(store, key)
.mount('#app')
问题及相关优化
- 如下样式配置,当直接在vue文件中使用,会发现定义的变量无法生效且报错,只有body这类的样式正常使用
// common.scss
body {
background-color: #000;
}
// variables.scss
$color: red;
- 我们需要引入定义的样式变量才能正常使用,但是每个单文件组件都引入是麻烦的。
<template>
<h1> demo </h1>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped>
@import '@/styles/variables.scss';
h1 {
color: $color;
}
</style>
- 采取 变量注入全局的方式
// vite.config.ts
css: {
preprocessorOptions: {
scss: {
// 注入样式变量(根据自己需求注入其他)
additionalData: '@import "@/styles/variables.scss;"'
}
}
}
- 就可以直接使用变量
<style lang="scss" scoped>
h1 {
color: $color;
}
</style>
基于axios封装请求模块
下载axios
npm i axios
封装request请求模块
import axios from 'axios'
// 创建实例
const request = axios.create({
baseURL: 'http:localhost:3030'
})
// 请求拦截器
request.interceptors.request.use(function (config) {
// 统一设置用户身份 token(根据项目需求配置)
return config
}, function (error) {
return Promise.reject(error)
})
// 响应拦截器
request.interceptors.response.use(function (response) {
// 统一处理接口响应错误,token过期无效、服务端异常等(根据项目需求配置)
return response
}, function (error) {
return Promise.reject(error)
})
export default request
基本使用
import request from './request'
interface ReposeeData<T = any> {
status: number
name: string
age: number
obj: T
}
export const getUserInfo = () => {
return request.get<ReposeeData<{
hi: string
slide: string
}>>('/user/info')
}
封装泛型请求方法
- 原生的axios是不支持泛型的
- 我们对request进行一层包装
import axios, { AxiosRequestConfig } from 'axios'
// 创建实例
const request = axios.create({
baseURL: 'http:localhost:3030'
})
// 请求拦截器
request.interceptors.request.use(function (config) {
// 统一设置用户身份 token
return config
}, function (error) {
return Promise.reject(error)
})
// 响应拦截器
request.interceptors.response.use(function (response) {
// 统一处理接口响应错误,token过期无效、服务端异常等
return response
}, function (error) {
return Promise.reject(error)
})
// 包装request,实现泛型
export default <T = any> (config: AxiosRequestConfig) => {
return request(config).then(res => {
return res.data as T
})
}
- 调用
import request from './request'
// 返回数据类型声明
interface ReposeeData<T = any> {
status: number
name: string
age: number
obj: T
}
export const getLogin = () => {
return request<ReposeeData>({
method: 'GET',
url: '/login/info'
})
}
环境变量和模式
-
在vite中支持环境变量的自定义
-
创建 .env.development 文件
# 开发模式下加载的环境变量
VITE_API_BASEURL = 'https://abc.com/development/api'
- 创建 .env.production 文件
# 生成模式下加载的环境变量
VITE_API_BASEURL = 'https://abc.com/production/api'
- env.d.ts 文件中声明自定义环境变量类型
/// <reference types="vite/client" />
declare module '*.vue' {
import type { 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 extends Readonly<Record<string, string>> {
readonly VITE_API_BASEURL: string
// 更多环境变量...
}
// eslint-disable-next-line no-unused-vars
interface ImportMeta {
readonly env: ImportMetaEnv
}
跨域问题
CORS(跨域资源共享)
- 服务端配置CORS
- 后端配置一些http协议
服务器代理模式
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 实例
'/apis': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
configure: (proxy, options) => {
// proxy 是 'http-proxy' 的实例
}
}
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)