一、使用vite创建项目
npm create vite@latest
当出现下面这一段话的时候,是在提示请输入你的项目名称(我这里用的是myProject
),然后按2下回车就可以了。
这里是选择搭建的项目框架,我们选择vue,然后按回车
这里已经是选择了TypeScript了,我们直接按回车就可以
当出现这三行消息的时候,就说明我们已经安装好了,然后依次执行这三行消息就可以了!
cd myProject
npm install
npm run dev
执行成功后就会出现以下消息,就说明已经运行成功了
我们直接复制Local后面的去浏览器打开就可以看到运行的结果了
二、安装css预处理器(sass)
scss是css的一种预处理器,可以大大提高css的维护性和可读性。它是动态样式表语言,可以赋予css动态语言的特性,例如变量,嵌套,继承,Mixin等,可以更加方便的对样式进行模块化开发。
npm install -D sass
使用测试,我们去项目的app.vue文件中使用一下:
这里是原本的代码
改完后
<style lang="scss" scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
&:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
&.vue {
&:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
}
}
</style>
改完后,再打开页面没看到有变化就说明sass安装成功了
三、初始化样式 normalize.css
npm i normalize.css
在main.ts中使用
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 导入 router
import 'normalize.css'; // 引入 normalize.css
const app = createApp(App);
app.use(router); // 使用 router
app.mount('#app');
四、配置 src 路径别名
1.vite.config.ts
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import type { UserConfig, ConfigEnv } from 'vite'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
return {
plugins: [
vue(),
],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
}
})
2.tsconfig.json
// tsconfig.json
{
"compilerOptions": {
// 配置@路径别名
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
// ...其他配置
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
}
五、安装Router
1.npm安装
npm i vue-router@4
2.创建router文件
在src下创建一个 router 文件夹,再创建一个 index.ts 文件
// router/index.ts
import { createRouter, createWebHashHistory } from 'vue-router';
import type { RouteRecordRaw } from 'vue-router';
const routes: Array<RouteRecordRaw> = [
{
name: 'Main',
path: '/',
meta: {
title: 'Main',
},
component: () => import('@/views/Main/Main.vue'),
},
// 页面不存在时的路由
{
name: '404',
path: '/:pathMatch(.*)*',
meta: {
title: '404',
},
component: () => import('@/views/Error/404.vue'),
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
3.在main.ts中使用router
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 导入 router
import 'normalize.css'; // 引入 normalize.css
const app = createApp(App);
app.use(router); // 使用 router
app.mount('#app');
六、安装 Element Plus
安装
npm install element-plus --save
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import 'normalize.css';
import ElementPlus from 'element-plus'; // 引入 ElementPlus
import 'element-plus/dist/index.css'; // 引入 ElementPlus 的 css 文件
const app = createApp(App);
app.use(router);
app.use(ElementPlus); // 使用 ElementPlus
app.mount('#app');
然后我们找一个页面使用一下,看看是否安装配置好了
<template>
<div class="view">Main</div>
<div>
<!-- 使用 ElButton -->
<el-button>Default</el-button>
<el-button type="primary">Primary</el-button>
<el-button type="success">Success</el-button>
<el-button type="info">Info</el-button>
<el-button type="warning">Warning</el-button>
<el-button type="danger">Danger</el-button>
</div>
</template>
<script setup lang="ts">
import { ElButton } from 'element-plus'; // 引入组件
</script>
<style lang="scss" scoped>
/* by wdTomato */
</style>
效果如下
七、配置自动化导入
配置自动化导入可以让我们提高我们开发的效率,可以避免我们需要频繁引入经常使用的api以及ui组件,例如vue中的ref,reactive等和element的组件。
但需要注意的是,自定义的方法也配置自动化导入的话,后期在维护的时候可能会不好追溯源。
npm install -D unplugin-vue-components unplugin-auto-import
import { defineConfig,} from 'vite'
import type { UserConfig, ConfigEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// 引入自动导入 api
import AutoImport from 'unplugin-auto-import/vite'
// 引入配置需要自动导入的组件
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
return {
plugins: [
vue(),
AutoImport({
// 配置需要自动导入的模块
imports: ['vue', 'vue-router'],
resolvers: [ElementPlusResolver()],
dts: 'src/types/auto-import.d.ts',
}),
// 配置需要自动导入的组件
Components({
// 导入存放的位置
dts: 'src/types/components.d.ts',
resolvers: [ElementPlusResolver()],
}),
],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
}
})
配置好后我们就可以直接在.vue文件中使用vue的api,跟element组件了,不要再手动引入
八、使用仓库管理(Pinia)
Pinia是vue新的存储库,它可以让我们在跨组件通信的时候更加的方便快捷。由于Pinia是基于Vue3的Composition API 构建的,相对于Vuex用Option API更加的轻量级,易上手。可以让我们更轻松的管理存储数据。
1.安装
npm install pinia
# 或者使用 yarn
yarn add pinia
2.使用
在src目录下创建store文件夹,再创建一个index.ts文件
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
// 全局注册 store
export function setupStore(app: App<Element>) {
app.use(store);
}
export default store;
在main中引入useStore
方法使用
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import 'normalize.css';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import { useStore } from './store'; // 引入 store
const app = createApp(App);
app.use(router);
app.use(ElementPlus);
app.use(useStore); // 使用 store
app.mount('#app');
3.使用例子
在store文件夹下创建一个modules的文件夹,再创建一个counter.ts的文件
// store/modules/counter.ts
import { defineStore } from 'pinia'; // 引入 defineStore
// 创建一个 counter store
export const useCounterStore = defineStore('counter', () => {
// 创建一个 count 变量
const count = ref(0);
// 创建一个 increment 方法
const increment = () => count.value++;
// 返回 count 和 increment
return {
count,
increment,
};
});
在页面中使用
<template>
<div class="view">
<h1>Main + {{ counterStore.count }}</h1>
<el-button type="primary" @click="increment">+ 1</el-button>
</div>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/store/modules/counter'; // 引入store
const counterStore = useCounterStore(); // 使用store
// 使用store中的方法
const increment = () => {
counterStore.increment();
};
</script>
<style lang="scss" scoped>
/* by wdTomato */
.view {
margin: 200px auto;
text-align: center;
}
</style>
运行效果
4.Pinia数据持久化
1).安装
npm i pinia-plugin-persistedstate
2).配置
// store/index.ts
import type { App } from 'vue';
import { createPinia } from 'pinia';
import piniaPersist from 'pinia-plugin-persistedstate'; // 引入持久化插件
const store = createPinia();
store.use(piniaPersist); // 使用 piniaPersist
export function useStore(app: App<Element>) {
app.use(store);
}
export default store;
3).使用
// 在需要持久化的仓库启用
import { defineStore } from 'pinia';
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0);
const increment = () => count.value++;
return {
count,
increment,
};
},
{ persist: true } // 启用持久化
);
4).效果
九、配置 env 环境
1.创建文件
在项目的根目录创建 .env.development
、.env.production
这两个文件
- 开发环境
# 开发环境
# 应用标题
VITE_TITLE = 'My-Admin-Dev'
# 端口号
VITE_PORT = 4090
#应用api前缀
VITE_BASE_API = '/dev-api'
# 代理指向地址
VITE_TARGET_URL = 你的接口地址
- 生产环境
## 生产环境
# 应用标题
VITE_TITLE = 'My-Admin'
# 端口号
VITE_PORT = 4090
#应用api前缀
VITE_BASE_API = '/prod-api'
# 代理指向地址
VITE_APP_TARGET_URL = 你的接口地址
十、Axios
1.安装
npm i axios
2.处理请求,响应拦截
- 在src下创建
service/request/index.ts
文件
import axios from 'axios'
import type { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import { openLoading, closeLoading } from '@/hooks/useLoading.ts' // 引入开启、关闭 loading
// 创建 axios 示例
const request = axios.create({
baseURL: import.meta.env.VITE_BASE_API, // 配置基础请求地址(配置方法在前面的 env 环境)
timeout: 10000, // 请求超时时间
headers: { 'Content-Type': 'application/json;charset=utf-8' }, // 请求头
})
let loading = false
// 请求拦截
request.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// config 可以拿到我们发送的请求内容,在这里可以配置请求权限,是否有token,根据自己的业务来写逻辑,也可以在这里根据需求修改请求头,请求类型请求时间。。。。
// 判断是否需要 Loading
if (!config.hideLoading) {
openLoading() // 打开 Loading
loading = true
}
console.log('config', config)
return config // 这里必须要 return出去
},
(err: any) => {
// 请求出错,关闭 Loading,用 Promise 返回错误
console.log('request err', err)
if (loading) closeLoading()
ElMessage.error({
message: err.msg || '接口请求异常',
})
return Promise.reject(err)
}
)
// 响应拦截
request.interceptors.response.use(
(response: AxiosResponse) => {
// 请求内容响应回来,可以在这里做接口判断,可以通过后端返回请求状态码判断,根据后端接口来
const { data } = response
// 我这里成功状态码是 200
if (response.status && response.data.code === 200) {
if (loading) closeLoading()
return data
}
// 如果不是 200 则返回错误
if (loading) closeLoading()
ElMessage.error({
message: err.msg || '接口返回异常',
})
return Promise.reject(data)
},
(err: any) => {
// 响应出错,关闭 Loading,用 Promise 返回错误
if (loading) closeLoading()
console.log(err)
ElMessage.error({
message: err.msg || '接口返回异常',
})
return Promise.reject(err)
}
)
export default request
- 创建
src/hooks/useLoading.ts
,loading hook
// useLoading.ts
import { ElLoading } from 'element-plus'
let loading: { close: () => void }
function openLoading() {
loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
}
function closeLoading() {
loading.close()
}
export { openLoading, closeLoading }
如果ElMessage
或者ElLoading
报错,可能是先前配置自动导入没配置好,需要自己在文件手动导入
import { ElMessage, ElLoading } from 'element-plus'
3.前端配置反向代理,解决跨域
import { defineConfig, loadEnv } from 'vite'
import type { UserConfig, ConfigEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// 引入自动导入 api
import AutoImport from 'unplugin-auto-import/vite'
// 引入配置需要自动导入的组件
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
const env = loadEnv(mode, process.cwd())
return {
plugins: [
vue(),
AutoImport({
// 配置需要自动导入的模块
imports: ['vue', 'vue-router'],
resolvers: [ElementPlusResolver()],
dts: 'src/types/auto-import.d.ts',
}),
// 配置需要自动导入的组件
Components({
// 导入存放的位置
dts: 'src/types/components.d.ts',
resolvers: [ElementPlusResolver()],
}),
],
// 配置代理
server: {
port: Number(env.VITE_PORT), // 启动端口号(配置在.env)
open: true, // 是否启动就打开浏览器
// 反向代理
proxy: {
[env.VITE_BASE_API]: {
target: env.VITE_TARGET_URL,
changeOrigin: true,
rewrite: (path) =>
path.replace(
new RegExp(`^${env.VITE_BASE_API}`),
env.VITE_TARGET_URL
), // 路径重写
},
},
},
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
}
})
4.发送请求
按照我自己的习惯,我会在src创建一个api文件夹存放请求,方便管理
举个例子,在api文件夹下创建一个文件index.ts
import { AxiosPromise } from 'axios'
import request from '../request/index.ts'
// 查询参数接口
interface IQuery {
page: number // 请求页码
pageSize: number // 请求多少条数据
}
// 响应接口
interface ITableList {
code: number // 响应状态码
data: any[] // 响应数据
msg: string // 响应消息
}
// 请求例子
export function getTableApi(queryParams: IQuery): AxiosPromise<ITableList> {
return request({
url: '/api/user/getAll', // 接口路径
method: 'get', // 请求方法 get,post,put。。。
params: queryParams, // 请求参数
hideLoading: true, // 是否隐藏 loading,默认为不隐藏
})
}
在组件(.vue 文件)中使用
<script setup lang="ts">
import { getTableApi } from '@/service/api/index.ts' // 引入接口方法
const getData = async () => {
try {
const res = await getTableApi({ page: 1, pageSize: 10 })
console.log(res)
} catch (e) {
// TODO handle the exception
console.log(e)
}
}
getData()
</script>
结语
感谢阅读,有啥问题或者建议可以在评论中给我指出来!