1. 使用Vite创建项目
npm create vite@latest 兼容性注意: Vite v3+ 需要 Node.js 版本 14.18+,16+ Vite v2+ 需要 Node.js 版本 12.2.0+
使用Git Bash Here 创建项目时,会出现无法上下切换选项的问题,所以一般是在当前文件夹下使用cmd 创建项目
当前目录下打开cmd: 创建项目:
- Project name : <项目名称>
- Select a framework : <选择一个框架,一般都是vue吧>
- Select a variant : <不知道怎么翻译>,应该是语言基础吧?一般都是选择js或者ts
2. 启动项目并做基本的配置
- 使用
npm install 下载基本的依赖 - 使用
npm run dev 运行项目(这两步在创建完项目之后都会提示你做的)
这是一个基本的目录结构
node_modules 存放(npm install 之后)项目的依赖public 存放一些基本的公共文件,如 icon 等src 文件,开发最常用的文件夹,所有资源都放在这个文件夹下面
src 文件下几个文件的解读
App.vue vue项目的主组件,createApp 时 需要传入的根组件,页面入口文件 ,所有页面都是在App.vue下进行切换的。是整个项目的关键,app.vue负责构建定义及页面组件归集。 一般情况下,这个页面里面什么都不做,只放一个 router-view 路由视图组件就完事了main.js 项目的入口文件,主要作用是初始化vue实例,并引入所需要的插件
- 实例化vue,上面提到的
createApp - 引入各类插件,
axios,elementUI 等,引入css 样式 - 存储用户的全局变量等
package.json 这个文件要说的东西要多了 可以点击链接直接去看看这位师兄的,很详细 另外 package.json 最好和 package-lock.json 一起学习使用vite.config.js vite的官方配置文档,东西多的很,不是一时半会就能学完的,只能说用到的时候去看就行
使用vite需要注意的几个点
- vite中没法使用@来指代src目录,需要手动配置
import path from "path";
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
- vite中
无法使用 require 引入文件(CommonJS 模块化规范),vite只支持ESModules 模块化规范 最好也别想着用什么插件强制使用require啥的,没必要
基本配置1:环境变量的配置
vite 和webpack 类似的环境变量配置方案,使用.env文件创建不同的环境配置文件,再在文件中进行相关的环境字段配置 注意,要想在全局中使用,首字母开头必须是 VITE 这样我们就可以在其他文件中使用 import.meta.env 访问到当前的环境变量了
package.json 还要进行配置,告诉项目,我们当前使用的是什么环境运行命令、打包命令 使用 --mode < env > 的形式
最后在 vite.config.js 也需要一点环境变量的配置 这里我这要配置了【静态资源 CDN】加速的配置,其他跟环境变量没有太大关系,主要是认识 loadEnv
import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig(({ command, mode }) => {
const staticPath = loadEnv(mode, "./", "BASE_URL").BASE_URL || "./";
return {
base: mode == "dev" ? "./" : staticPath,
build: {
assetsDir: "static",
},
plugins: [vue()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
};
});
基本配置2:封装axios,及请求的全局loading
npm install axios 下载 axios 下载之后不需要在main.js 中进行引入,直接在需要的地方引入就行了
request.js文件 封装了【请求】、【响应】拦截器,三个常用的请求方法,全局loading 这样最基础的一个axios 请求就封装好了
import axios from "axios";
import { getToken, removeToken } from "@/utils/auth";
import { startLoading, endLoading } from "./requestLoading";
import myRouter from "../router/index";
import { ElMessage } from "element-plus";
const myProcess = import.meta.env;
const service = axios.create({
baseURL: myProcess.VITE_APP_API,
timeout: 1000 * 30,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
});
service.interceptors.request.use(
(config) => {
if (config.headers.showLoading) {
startLoading();
}
if (getToken() && getToken() !== undefined) {
config.headers["token"] = getToken();
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
service.interceptors.response.use(
(response) => {
endLoading();
if ([401, 403].includes(response.data.code)) {
removeToken();
myRouter.push({ name: "login" });
}
return response;
},
(error) => {
endLoading();
ElMessage.error(error.message);
return Promise.reject(error);
}
);
export const get = (url, params, showLoading) => {
return service({
url: url,
method: "get",
params,
headers: { showLoading },
});
};
export function postFormData(url, data, showLoading) {
return service({
url,
method: "post",
headers: { "Content-Type": "application/x-www-form-urlencoded", showLoading },
transformRequest: [
function (data) {
let ret = "";
for (const it in data) {
ret += encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&";
}
return ret;
},
],
data,
});
}
export function postJson(url, data, showLoading) {
return service({
url,
method: "post",
data,
headers: { "Content-Type": "application/json", showLoading },
});
}
export default service;
requestLoading.js 文件
import { ElLoading } from "element-plus";
let requestNum = 0;
let loading;
export function startLoading() {
if (requestNum === 0) {
loading = ElLoading.service({
lock: true,
text: "Loading",
background: "rgba(0, 0, 0, 0.7)",
});
}
requestNum++;
}
export function endLoading() {
setTimeout(closeLoading, 300);
}
function closeLoading() {
if (requestNum <= 0) return;
requestNum--;
if (requestNum === 0) {
loading.close();
}
}
基本配置3:vue-router路由的引入并使用
在创建vite 项目的时候,vue-router 并不是自带的,因为vue 的本质是一个渐进式框架,我们需要手动引入并配置路由
npm install vue-router@4 点击查看vue-router官方文档
下载完成后,我们在src目录下新建一个router 文件夹,文件夹中新建一个index.js ,初始并实例化我们的router index.js文件
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
{
path: "/",
name: "login",
component: () => import( "../views/login/index.vue"),
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
最后引入到我们的main.js 文件中,并使用
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router/index";
const app = createApp(App);
app.use(router)
app.mount("#app");
基本配置4:配置css预处理器,这里以less 为例
没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖 直接执行完命令就可以使用less 了 npm add -D less vite 官方文档CSS预处理器
基本配置5:layout页面的搭建
首先我们下载element-ui-plus ,使用element 的container 布局容器进行页面结构布局
npm install element-plus --save 官方文档
下载element icon 这个路由左侧的icon 会用到 npm install @element-plus/icons-vue
在mian.js 中引入
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router/index";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.use(router);
app.use(ElementPlus);
app.mount("#app");
挑选一个自己喜欢的布局容器 布局里面着重说一下侧边栏的设计
<template>
<div class="common-layout">
<el-container>
<el-aside width="200px" class="aside_wrap">
<el-scrollbar>
<el-menu
active-text-color="#ffd04b"
background-color="#545c64"
class="el-menu-vertical-demo"
text-color="#fff"
:default-active="defaultActive"
>
<myAside :mainRouterList="mainRouterList"></myAside>
</el-menu>
</el-scrollbar>
</el-aside>
<el-container>
<el-header class="header_wrap">
<myHeader></myHeader>
</el-header>
<el-main class="main_wrap">
<myMain></myMain>
</el-main>
<el-footer>Footer</el-footer>
</el-container>
</el-container>
</div>
</template>
<script setup>
import myAside from "../layout/components/myAside/myAside.vue";
import myHeader from "../layout/components/myHeader/myHeader.vue";
import myMain from "../layout/components/myMain/myMain.vue";
import { useRoute, useRouter } from "vue-router";
import { ref } from "vue";
const myRouter = useRouter();
const myRoute = useRoute();
const routerList = myRouter.options.routes;
const mainRouterList = routerList.find((v) => v.name == "home").children;
const defaultActive = ref("");
defaultActive.value = myRoute.path;
</script>
<style lang="less" scoped>
.aside_wrap {
background-color: rgb(136, 136, 136);
height: 100vh;
}
.header_wrap {
background-color: rgb(220, 243, 255);
}
.main_wrap {
background-color: #c7c7c7;
height: 100%;
}
</style>
使用递归的形式,循环调用el-menu 里面的el-sub-menu和el-menu-item myAside 文件里代码
<template>
<template v-for="item in myMainRouterList" :key="item.name">
<!-- 多个 -->
<el-sub-menu :index="item.path" v-if="item?.children?.length > 0">
<template #title>
<el-icon><component :is="item?.meta?.icon"></component></el-icon>
<span>Navigator One</span>
</template>
<!-- 递归调用自己 -->
<myAside :mainRouterList="item?.children"></myAside>
</el-sub-menu>
<!-- 单个 -->
<el-menu-item :index="item.path" v-else @click="handleClickMenu(item)">
<el-icon><component :is="item?.meta?.icon"></component></el-icon>
<span>Navigator Two</span>
</el-menu-item>
</template>
</template>
<script setup>
import { defineProps } from "vue";
import { useRouter } from "vue-router";
const myRouter = useRouter()
const myProps = defineProps(["mainRouterList"]);
const myMainRouterList = myProps.mainRouterList;
const handleClickMenu = (subItem) => {
myRouter.push(subItem?.path);
};
</script>
然后再随便撸一个路由
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
{
path: "/",
name: "login",
component: () => import( "../views/login/index.vue"),
},
{
path: "/home",
name: "home",
redirect: { name: "page1" },
component: () => import("../views/layout/index.vue"),
children: [
{
path: "/page1",
name: "page1",
meta: { icon: "CirclePlus", title: "页面11" },
redirect: { name: "page1-1" },
children: [
{
path: "/page1-1",
name: "page1-1",
meta: { icon: "Link", title: "页面1-1" },
component: () => import("../views/pages/components/page1-1.vue"),
},
{
path: "/page1-2",
name: "page1-2",
meta: { icon: "Position", title: "页面1-2" },
component: () => import("../views/pages/components/page1-2.vue"),
},
],
},
{
path: "/page2",
name: "page2",
meta: { icon: "Female", title: "页面22" },
component: () => import("../views/pages/page2.vue"),
},
{
path: "/page3",
name: "page3",
meta: { icon: "Male", title: "页面33" },
component: () => import("../views/pages/page3.vue"),
},
],
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
好的,这样一个基本的后台管理系统框架就搭建完成了!
|