1、创建项目
采用vite创建vue项目
yarn create vite my-vue-app --template vue-ts
2、添加路由
yarn add vue-router@4
在src下创建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
创建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: 自定义拦截内容
console.log(to, from, next)
next();
});
export default router
在main.ts 下引用router
import router from '@/router/index'
createApp(App).use(router)
这个时候会报错@找不到,这个我们随后会配置。这里可以暂时改成用../来引用
3、添加pinia
yarn add pinia
src下创建store文件夹并添加文件index.ts 添加文件夹modules,modules下添加app.ts以及user.ts
index.ts内容
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)
这个跟路由一样 可以先改成用../引用
4、设置‘@’
在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,这种组件需要手动加载在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
这个插件我感觉很好用 可以少些很多样式代码
yarn add vite-plugin-windicss windicss -D
然后,在你的 Vite 配置中添加插件vite.config.ts
import WindiCSS from 'vite-plugin-windicss'
export default {
plugins: [
WindiCSS(),
],
}
最后,在你的 Vite 入口文件中导入 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, // 基础 url
timeout: 10000 // 超时 10s
});
// 请求拦截器
axios.interceptors.request.use(
config => {
// TODO: 配置请求内容
// config.headers.Authorization = `Bearer ${token}`;
return config;
},
error => {
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
response => {
// TODO: 配置对响应内容的处理
return response;
},
error => {
let { response } = error;
if (error && error.response) {
switch (error.response.status) {
case 400:
response.message = '未知错误';
break;
case 401:
response.message = '未授权';
break;
case 403:
response.message = '权限不足';
break;
case 404:
response.message = '数据不存在';
break;
case 405:
response.message = '不允许的请求方法';
break;
case 408:
response.message = '请求超时';
break;
case 415:
response.message = '不支持的媒体类型';
break;
case 500:
response.message = '服务器出现异常';
break;
case 501:
response.message = '网络未实现';
break;
case 502:
response.message = '网络错误';
break;
case 503:
response.message = '服务不可用';
break;
case 504:
response.message = '网络超时';
break;
case 505:
response.message = 'http版本不支持该请求';
break;
default:
response.message = `其他错误。错误代码:${error.response.status}`;
}
} else {
response = { message: '无法连接到服务器!' };
}
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": {
// 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
"allowSyntheticDefaultImports": true,
// 解析非相对模块名的基准目录
"baseUrl": ".",
"esModuleInterop": true,
// 从 tslib 导入辅助工具函数(比如 __extends, __rest等)
"importHelpers": true,
// 指定生成哪个模块系统代码
"module": "esnext",
// 决定如何处理模块。
"moduleResolution": "node",
// 启用所有严格类型检查选项。
// 启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict,
// --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。
"strict": true,
// 生成相应的 .map文件。
"sourceMap": true,
// 忽略所有的声明文件( *.d.ts)的类型检查。
"skipLibCheck": true,
// 指定ECMAScript目标版本
"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: './', // 设置打包路径
server: {
port: 3030, // 设置服务启动端口号
open: true, // 设置服务启动时是否自动打开浏览器
cors: true // 允许跨域
// 设置代理,根据我们项目实际情况配置
// proxy: {
// '/api': {
// target: 'http://xxx.xxx.xxx.xxx:8000',
// changeOrigin: true,
// secure: false,
// rewrite: (path) => path.replace('/api/', '/')
// }
// }
}
})
这样就可以用@符号代替src了