Vite + Typescript + Ant Design Vue / Element-plus 搭建后台管理项目
前段时间使用了Vite + Typescript + Ant Design Vue搭建项目,写下搭建步骤,方便下次使用~
根据项目的实际情况进行配置
1. Vite 项目初始化配置
初始化
对比 Vue-cli(基于 Webpack),Vite 非常非常快❤!
vite 官方中文文档:cn.vitejs.dev/guide/
个人喜欢用yarn,命令简单统一
安装 vite
1
yarn create vite
按照提示输入就ok了
浏览器打开查看效果:http://localhost:3000/
配置别名
修改 vite.config.ts 配置文件
1 |
|
报错:找不到模块“path”或其相应的类型声明;找不到名称“__dirname”
1
yarn add @types/node --save-dev
报错:Cannot find module ‘store/index’ or its corresponding type declarations.
在 tsconfig.json 中配置 baseUrl 和 paths
1
2
3
4
5
6
7
8
9
10
11{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@": ["src/*"],
"comps/*": ["src/components/*"],
"store/*": ["src/store/*"]
}
}
}
2. 清空默认文件
新建 public/css/reset.css 文件,清除浏览器默认样式,并在main.ts引入 import '../public/css/reset.css'
1 |
|
将 src/assets
和 src/components
目录下的所有文件都删除
打开App.vue
文件,删除所有代码,使用快捷键vue生成模板
vscode设置模板
【文件】 -> 【首选项】 -> 【用户片段】 -> 【新建全局代码片段文件】 -> 输入文件名
vue-ts-less
-> 粘贴以下代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"Print to console": {
"prefix": "vue-ts-less",
"body": [
"<template></template>",
"",
"<script lang=\"ts\">",
"import { defineComponent } from \"vue\";",
"export default defineComponent({",
" components: {},",
" setup() {",
" return {};",
" },",
"});",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"$2"
],
"description": "Vue-ts-less模板"
}
}在vue文件输入
vue-ts-less
后按Tab键生成对应的代码块
3. Vuex 配置
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- 多个组件使用相同数据的
- 组件深嵌套
存在上述情况使用vuex会更为合适
Vuex 官方文档:next.vuex.vuejs.org/
安装Vuex,使用4.x版本
1
yarn add vuex@next --save
在 src 目录下创建
store/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32import { InjectionKey } from "vue";
import { createStore, useStore as baseUseStore, Store } from "vuex";
import type { App } from "vue";
// 引入对应的模块
import { users } from "./modules/users";
// 手动声明 state 类型
export interface State { }
// 定义注入类型
const key: InjectionKey<Store<State>> = Symbol();
const store = createStore<State>({
state() { },
mutations: {},
actions: {},
// 使用模块
modules: { users },
});
// 将类型注入useStore,项目中引用的均为自定义的这个,覆盖了vuex提供的useStore
export function useStore() {
return baseUseStore(key);
}
export function setupStore(app: App<Element>) {
app.use(store, key);
}
export default store;创建
store/modules
文件夹,该文件夹里可以新建各个module文件例如 user.ts
1
2
3
4
5
6
7
8
9
10import { createStore } from "vuex";
export interface State { }
export const users = createStore<State>({
state: () => ({}),
getters: {},
mutations: {},
actions: {},
})在main.ts中加入
1
2
3
4
5
6
7
8
9import { createApp } from "vue";
import { setupStore } from "./store";
import App from "./App.vue";
const app = createApp(App);
setupStore(app);
app.mount("#app");
4. Vue Router 4.x 配置
功能包括:
- 嵌套路由映射
- 动态路由选择
- 模块化、基于组件的路由配置
- 路由参数、查询、通配符
- 展示由 Vue.js 的过渡系统提供的过渡效果
- 细致的导航控制
- 自动激活 CSS 类的链接
- HTML5 history 模式或 hash 模式
- 可定制的滚动行为
- URL 的正确编码
Vue Router 官方中文文档:next.router.vuejs.org
安装
1
yarn add vue-router@4
修改App.vue文件
加上
router-view
标签才会起作用1
2
3
4
5
6
7
8
9
10
11
12<template>
<router-view></router-view>
</template>
<script lang="ts">
export default {
name: "App",
};
</script>
<style></style>在 src 目录下新建 router/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import { createRouter, createWebHistory } from "vue-router";
import type { App } from "vue";
// 导入对应的模块
const Home = () => import("../view/home.vue");
const Login = () => import("../view/login.vue");
// 写路由
const routes = [
{ path: "/", component: Home },
{ path: "/login", component: Login },
];
const router = createRouter({
// createWebHashHistory (hash路由)
// createWebHistory (history路,需要服务器配置支持)
// createMemoryHistory 带缓存 history 路由
// 添加baseUrl,createWebHistory(baseUrl)
history: createWebHistory(),
routes,
});
export function setupRouter(app: App<Element>) {
app.use(router);
}
export default router;项目大的话可以将路由分模块抽离出来
main.ts 修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14import { createApp } from "vue";
import { setupStore } from "./store";
import router, { setupRouter } from "./router";
import App from "./App.vue";
const app = createApp(App);
setupRouter(app);
setupStore(app);
router.isReady().then(() => {
app.mount("#app");
});
5. Scass / Scss / Less 预处理器
antd使用的是less
1 |
|
6. Ant Design of Vue 安装及配置
官网:https://2x.antdv.com/docs/vue
安装
1
yarn add ant-design-vue@next --save
在 main.ts 完整引入(不推荐)
1
2
3
4
5
6
7
8
9import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/antd.css'; // 要引入才有样式
const app = createApp();
app.config.productionTip = false;
app.use(Antd);局部导入
1
2
3
4
5
6
7
8
9
10import { createApp } from 'vue';
import { Button } from 'ant-design-vue';
import 'ant-design-vue/es/button/style'; //同样要引入less样式
import "ant-design-vue/es/button/style/css"; // 加载 CSS
import App from './App';
const app = createApp(App);
app.use(Button).mount('#app');==按需导入(推荐)==
安装 vite-plugin-imp
1
yarn add vite-plugin-imp -D
修改 vite.config.ts 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import { defineConfig } from "vite";
import vitePluginImp from "vite-plugin-imp";
export default defineConfig({
plugins: [
vue(),
vitePluginImp({
libList: [
{
libName: "ant-design-vue",
// style: (name) => `ant-design-vue/es/${name}/style/css`, // 加载css
style: (name) => `ant-design-vue/es/${name}/style`, // 加载less
},
],
}),
],
css: {
preprocessorOptions: {
less: {
// 自定义定制主题
modifyVars: { "primary-color": "#1188ff" },
javascriptEnabled: true,
},
},
},
});在 src 目录下新增 libs/antdv.ts 文件
1
2
3
4
5
6
7
8
9
10
11import type { App } from "vue";
// 新增组件就在这里进行新增就可以了
import { Button, Radio, Checkbox } from "ant-design-vue";
const components = [Button, Radio, Checkbox];
export function setupAntd(app: App<Element>): void {
components.forEach((component: any) => {
app.use(component);
});
}修改main.ts文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import { createApp } from "vue";
import { setupStore } from "./store";
import router, { setupRouter } from "./router";
import { setupAntd } from "./libs/antdv"; // ++
import App from "./App.vue";
const app = createApp(App);
setupRouter(app);
setupStore(app);
setupAntd(app); // ++
router.isReady().then(() => {
app.mount("#app");
});
7. Element-plus 安装及配置
这里只讲述使用插件按需导入,其他可以到官网看,和上面的antd差不多
官方文档:https://element-plus.gitee.io/zh-CN/
安装
1
yarn add element-plus
自动导入
1
yarn add unplugin-vue-components unplugin-auto-import
修改 vite.config.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}同样的,在 src 目录下新增 libs/elem.ts 文件
1
2
3
4
5
6
7
8
9
10import type { App } from "vue";
import { ElButton } from 'element-plus'
const components = [ElButton];
export function setupElem(app: App<Element>): void {
components.forEach((component: any) => {
app.use(component);
});
}修改main.ts文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import { createApp } from "vue";
import { setupStore } from "./store";
import router, { setupRouter } from "./router";
import { setupElem } from "./libs/element-plus"; // ++
import App from "./App.vue";
const app = createApp(App);
setupRouter(app);
setupStore(app);
setupElem(app); // ++
router.isReady().then(() => {
app.mount("#app");
});
8. axios 安装及二次封装
Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post等请求
- 可以在浏览器中发送 XMLHttpRequests
- 可以在 node.js 发送 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 能够取消请求
- 自动转换 JSON 数据
- 客户端支持保护安全免受 XSRF 攻击
github网址:https://github.com/axios/axios
安装
1
yarn add axios
在 src 目录下新建
src/service/request.ts
对axios进行二次封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import { message } from 'ant-design-vue'
import { useRouter } from "vue-router"
const router = useRouter()
export function request(config: AxiosRequestConfig) {
// 1 创建实例
const instance = axios.create({
baseURL: "xxx",
timeout: 5000,
headers: {
"Content-Type": "application/json",
},
});
// 2 拦截器
// 请求拦截
instance.interceptors.request.use(
(config) => {
message.loading();
return config;
},
(err) => {
console.log(err);
}
);
// 响应拦截
instance.interceptors.response.use((response: AxiosResponse<any>) => {
message.loading('请稍等……', 0)
return response.data;
}),
(error: any) => {
if (error?.response) {
switch (error.response.status) {
case 400: message.error('请求错误(400)'); break;
case 401: router.push({ name: 'login' }); break;
case 403: message.error('拒绝访问(403)'); break;
case 404: message.error('请求出错(404)'); break;
case 408: message.error('请求超时(408)'); break;
case 500: message.error('服务器错误(500)'); break;
case 501: message.error('服务未实现(501)'); break;
case 502: message.error('网络错误(502)'); break;
case 503: message.error('服务不可用(503)'); break;
case 504: message.error('网络超时(504)'); break;
case 505: message.error('HTTP版本不受支持(505)'); break;
default: message.error(`连接出错(${error.response.status})!`);
}
} else {
message.error('连接服务器失败!');
}
message.destroy()
console.log(error);
};
// 3 返回实例,instance本身就是一个pormise
return instance(config);
}使用:
在 service 文件夹中新建api文件夹,在此文件夹中对api进行分模块编写
1
2
3
4
5
6
7
8
9
10
11import { request } from "../request";
export function xxxx() {
return request({
url: `xxx`,
method: 'get',
data: {},
params: {}
});
}在使用该api的文件中直接引入即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
<el-button @click="test">测试</el-button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { getSometings } from "../service/api/user";
export default defineComponent({
setup() {
const test = async () => {
await getSometings().then((res: any) => {
console.log(res.data);
});
};
return { test };
},
});
</script>
<style>
</style>u1s1 还写了挺久的。。。写了大半天时间ε=(´ο`*)))
感谢作者:时光足迹
链接:https://juejin.cn/post/6973913260257247245
来源:稀土掘金
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!