// 我用的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
文件名 | 用途 |
---|---|
api | 存放请求相关文件 |
layout | 布局 |
plugins | 插件 |
composables | 组合式 API 抽离方法 |
router | 路由 |
store | 仓储 |
styles | 公共样式 |
utils | 工具函数 |
views | 路由页面 |
npm install eslint -D
npx eslint --init
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
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"
},
npx mrm@2 lint-staged
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"npm run lint",
"git add"
]
}
npm install vite-plugin-eslint --save-dev
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 // 缓存,默认开启
})
]
})
npm i vue-router@4
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
// 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>
npm install vuex@next --save
// 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++
}
}
})
/* 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>
}
}
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')
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)
}
import path from 'path'
resolve: {
alias: {
// '@':'绝对路径', 若有需要,自行配置其他
'@': path.join(__dirname, 'src')
}
}
{
"compilerOptions": {
// 路径配置
"paths": {
"@/*": [
"./src/*"
]
}
}
}
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
npm i -D sass
@import './common.scss';
@import './mixin.scss';
@import './transitiono.scss';
@import './variables.scss';
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')
// 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>
npm i axios
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')
}
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'
# 生成模式下加载的环境变量
VITE_API_BASEURL = 'https://abc.com/production/api'
///
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
}
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' 的实例
}
}
}
}