1、創(chuàng)建項(xiàng)目
采用vite創(chuàng)建vue項(xiàng)目
yarn create vite my-vue-app --template vue-ts
2、添加路由
yarn add vue-router@4
在src下創(chuàng)建router文件夾
添加文件config.ts 存放文件路由
config.ts
import { RouteRecordRaw } from 'vue-router'
let layout = () => import('@/layout/index.vue')
const routers:Array<RouteRecordRaw> = [
{
path: '/',
name: 'index',
component: layout,
children:[
{
path: '/',
name: 'Home',
component: () => import('@/views/home/home.vue'),
},
{
path: 'user',
name: 'user',
component: () => import('@/views/user/user.vue')
},
]
},
{
path: '/login',
name: 'login',
component: () => import('@/views/login/login.vue')
},
]
export default routers
創(chuàng)建index.ts 文件 生成路由
import { createRouter, createWebHistory } from 'vue-router'
import routers from './config'
const router = createRouter({
history: createWebHistory(),
routes: routers
})
// 路由攔截器
router.beforeEach((to, from, next) => {
// TODO: 自定義攔截內(nèi)容
console.log(to, from, next)
next();
});
export default router
在main.ts 下引用router
import router from '@/router/index'
createApp(App).use(router)
這個(gè)時(shí)候會(huì)報(bào)錯(cuò)@找不到,這個(gè)我們隨后會(huì)配置。這里可以暫時(shí)改成用../來引用
3、添加pinia
yarn add pinia
src下創(chuàng)建store文件夾并添加文件index.ts 添加文件夾modules,modules下添加app.ts以及user.ts
index.ts內(nèi)容
import { createPinia } from 'pinia'
const store = createPinia()
export { store }
modules/app.ts
import { defineStore } from 'pinia'
interface stateType {
msg:string,
count:number
}
export const appStore = defineStore('app',{
state: ():stateType=>{
return {
count: 0,
msg: '15898970112'
}
},
getters: {
doubleNum:(state)=>{
console.log(111111,appStore)
return state.count * 2
}
},
actions: {
changeCount(){
this.count ++
}
}
})
modules/user.ts
import { defineStore } from 'pinia'
interface userStateType{
userName:string,
tel:string|number,
passWord:string|number,
userInfo?:Object
}
export const userStore = defineStore('user',{
state: ():userStateType=>{
return {
userName:'張三',
tel:'13838384388',
passWord:'123456'
}
},
getters: {
tonken:(state)=>{
console.log(state);
return '123456789'
}
},
actions:{
getUser(){
return {
userName:this.userName
}
}
}
})
在main.ts中引用
import { store } from '@/store/index'
createApp(App).use(router).use(store)
這個(gè)跟路由一樣 可以先改成用../引用
4、設(shè)置‘@’
在tsconfig.json中添加
"paths": {
"@/*": [
"src/*"
]
},
在vite.config.ts 下添加
resolve:{
alias: [
{
find: /\@\//,
replacement: pathResolve('src') + '/',
},
],
},
5、添加 Ant Design Vue
yarn add ant-design-vue@next
然后配置ant-design-vue按需加載
yarn add unplugin-vue-components -D
由于此插件無法處理非組件模塊,如 message,這種組件需要手動(dòng)加載在main.ts 下引用
import { message } from 'ant-design-vue';
import 'ant-design-vue/es/message/style/css';
createApp(App).use(message)
在vite.config.ts 下添加
import Components from 'unplugin-vue-components/vite'
import {
AntDesignVueResolver,
} from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
AntDesignVueResolver(),
],
})
],
})
6.添加Windi CSS
這個(gè)插件我感覺很好用 可以少些很多樣式代碼
yarn add vite-plugin-windicss windicss -D
然后,在你的 Vite 配置中添加插件vite.config.ts
import WindiCSS from 'vite-plugin-windicss'
export default {
plugins: [
WindiCSS(),
],
}
最后,在你的 Vite 入口文件中導(dǎo)入 virtual:windi.css:
main.ts
import 'virtual:windi.css'
7、配置axios
src下添加utils/http/index.ts utils/http/requests.ts
index.ts
import Axios from 'axios';
const baseURL = '';
const axios = Axios.create({
baseURL, // 基礎(chǔ) url
timeout: 10000 // 超時(shí) 10s
});
// 請(qǐng)求攔截器
axios.interceptors.request.use(
config => {
// TODO: 配置請(qǐng)求內(nèi)容
// config.headers.Authorization = `Bearer ${token}`;
return config;
},
error => {
return Promise.reject(error);
}
);
// 響應(yīng)攔截器
axios.interceptors.response.use(
response => {
// TODO: 配置對(duì)響應(yīng)內(nèi)容的處理
return response;
},
error => {
let { response } = error;
if (error && error.response) {
switch (error.response.status) {
case 400:
response.message = '未知錯(cuò)誤';
break;
case 401:
response.message = '未授權(quán)';
break;
case 403:
response.message = '權(quán)限不足';
break;
case 404:
response.message = '數(shù)據(jù)不存在';
break;
case 405:
response.message = '不允許的請(qǐng)求方法';
break;
case 408:
response.message = '請(qǐng)求超時(shí)';
break;
case 415:
response.message = '不支持的媒體類型';
break;
case 500:
response.message = '服務(wù)器出現(xiàn)異常';
break;
case 501:
response.message = '網(wǎng)絡(luò)未實(shí)現(xiàn)';
break;
case 502:
response.message = '網(wǎng)絡(luò)錯(cuò)誤';
break;
case 503:
response.message = '服務(wù)不可用';
break;
case 504:
response.message = '網(wǎng)絡(luò)超時(shí)';
break;
case 505:
response.message = 'http版本不支持該請(qǐng)求';
break;
default:
response.message = `其他錯(cuò)誤。錯(cuò)誤代碼:${error.response.status}`;
}
} else {
response = { message: '無法連接到服務(wù)器!' };
}
return Promise.reject(response);
}
);
export default axios;
requests.ts
import axios from './index';
/**
* @param promise
* @param errorExt - Additional Information you can pass to the err object
*/
function to<T, U = unknown>(
promise: Promise<T>,
errorExt?: object
): Promise<[U | null, T | undefined]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>(err => {
if (errorExt) {
Object.assign(err, errorExt);
}
return [err, undefined];
});
}
/**
* GET methods
* @param url
* @param data
* @returns {Promise}
*/
export function get<T>(url: string, params = {}): TO<T> {
return to(
new Promise((resolve, reject) => {
axios
.get(url, {
params
})
.then(result => {
resolve(result.data as T);
})
.catch(err => {
reject(err);
});
})
);
}
/**
* POST methods
* @param url
* @param data
* @returns {Promise}
*/
export function post<T>(url: string, data?: Record<string, unknown>): TO<T> {
return to(
new Promise((resolve, reject) => {
axios
.post(url, data)
.then(result => {
resolve(result.data as T);
})
.catch(err => {
reject(err);
});
})
);
}
/**
* PUT methods
* @param url
* @param data
* @returns {Promise}
*/
export function put<T>(url: string, data?: Record<string, unknown>): TO<T> {
return to(
new Promise((resolve, reject) => {
axios
.put(url, data)
.then(result => {
resolve(result.data as T);
})
.catch(err => {
reject(err);
});
})
);
}
/**
* DELETE methods
* @param url
* @param data
* @returns {Promise}
*/
export function del<T>(url: string, data?: Record<string, unknown>): TO<T> {
return to(
new Promise((resolve, reject) => {
axios
.delete(url, data)
.then(result => {
resolve(result.data as T);
})
.catch(err => {
reject(err);
});
})
);
}
下面附上完整的tsconfig.json文件以及vite.config.ts
tsconfig.json
{
"compilerOptions": {
// 允許從沒有設(shè)置默認(rèn)導(dǎo)出的模塊中默認(rèn)導(dǎo)入。這并不影響代碼的輸出,僅為了類型檢查。
"allowSyntheticDefaultImports": true,
// 解析非相對(duì)模塊名的基準(zhǔn)目錄
"baseUrl": ".",
"esModuleInterop": true,
// 從 tslib 導(dǎo)入輔助工具函數(shù)(比如 __extends, __rest等)
"importHelpers": true,
// 指定生成哪個(gè)模塊系統(tǒng)代碼
"module": "esnext",
// 決定如何處理模塊。
"moduleResolution": "node",
// 啟用所有嚴(yán)格類型檢查選項(xiàng)。
// 啟用 --strict相當(dāng)于啟用 --noImplicitAny, --noImplicitThis, --alwaysStrict,
// --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。
"strict": true,
// 生成相應(yīng)的 .map文件。
"sourceMap": true,
// 忽略所有的聲明文件( *.d.ts)的類型檢查。
"skipLibCheck": true,
// 指定ECMAScript目標(biāo)版本
"target": "esnext",
// 要包含的類型聲明文件名列表
"types": [
],
"jsx": "preserve",
"isolatedModules": true,
// 模塊名到基于 baseUrl的路徑映射的列表。
"paths": {
"@/*": [
"src/*"
]
},
// 編譯過程中需要引入的庫文件的列表。
"lib": [
"ESNext",
"DOM",
"DOM.Iterable",
"ScriptHost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": [
"node_modules"
]
}
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import WindiCSS from "vite-plugin-windicss";
import Components from 'unplugin-vue-components/vite'
import {
AntDesignVueResolver,
} from 'unplugin-vue-components/resolvers'
function pathResolve(dir: string) {
return resolve(process.cwd(), '.', dir);
}
export default defineConfig({
plugins: [
vue(),
WindiCSS(),
Components({
resolvers: [
AntDesignVueResolver(),
],
})
],
build: {
// 去除console
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
},
resolve:{
alias: [
{
find: /\@\//,
replacement: pathResolve('src') + '/',
},
],
},
base: './', // 設(shè)置打包路徑
server: {
port: 3030, // 設(shè)置服務(wù)啟動(dòng)端口號(hào)
open: true, // 設(shè)置服務(wù)啟動(dòng)時(shí)是否自動(dòng)打開瀏覽器
cors: true // 允許跨域
// 設(shè)置代理,根據(jù)我們項(xiàng)目實(shí)際情況配置
// proxy: {
// '/api': {
// target: 'http://xxx.xxx.xxx.xxx:8000',
// changeOrigin: true,
// secure: false,
// rewrite: (path) => path.replace('/api/', '/')
// }
// }
}
})
這樣就可以用@符號(hào)代替src了
完成項(xiàng)目地址:https://github.com/long3268671/vue3-vite-ts-demo