likes
comments
collection
share

一起来手撸一个管理后台vite+vue3--基础环境搭建

作者站长头像
站长
· 阅读数 45

前言

vue3已经发布一年多,之前把公司管理后台重vue2升级到vue3。后面又把vuex改成了pinia。最近又把构建工具重webpack改成了vite。渐进式的升级导致对这些技术都浅尝辄止。为此打算从零开始使用最新的技术栈搭建一个vue后台管理系统。加深下对这些新技术的印象和理解。

准备工作

  • VsCode 安装 Vue Language Features (Volar) 插件,支持<script setup>编译时语法糖
  • 创建一个项目 安装必要插件
    yarn create vite
    `Project name`: 输入项目名称
    `Select a template`: 选择vue
    //创建成功后 安装基础插件
    yarn add less less-loader vue-router pinia axios element-plus store 
    //安装完成后 允许项目
    yarn dev
    

目录介绍

├── public/
    ├── static/                    // 不需要打包的资源
└── src/
    ├── api/                       // 请求接口目录
    ├── assets/                    // 静态资源目录
        ├── image                  // 静态资源图片目录
        ├── styles                 // 静态资源样式目录
    ├── components/                // 公共组件目录
    ├── router/                    // 路由配置目录
    ├── store/                     // 状态管理目录
    ├── utils/                     // 工具函数目录
    ├── views/                     // 页面组件目录
    ├── App.vue
    ├── main.ts
├── index.html
├── vite.config.ts                 // Vite 配置文件
└── package.json

开始

  • vite.config.js 配置
//vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
    plugins: [vue()],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src'), //别名配置 在项目里可以使用 @ 表示 src 文件夹
        },
    },
    base: './', // 开发或生产环境服务的公共基础路径
    
})
  • Vue Router 配置
// src/router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';
import publics from './public';
import localStorage from 'store';
const router = createRouter({ history: createWebHashHistory(), routes: [...publics], });
router.beforeEach((to, from, next) => {
    if (to.path !== '/login' && !localStorage.get('token')) { // 判断是否存在用户token  不存在则重新登录
        next({ path: '/login' });
    } else {
        next()
    }
});
export default router;

// src/router/public.js
const routers = [{
    path: '/',
    name: 'Home',
    component: () =>
        import ( /* webpackChunkName: 'Home' */ '../views/public/Home.vue'),
}
// ... other router
];
export default routers;
// src/store/Public.js
import localStorage from 'store'
import { defineStore } from 'pinia'
export const PublicStore = defineStore('Public', {
    state: () => {
        return {
            userMsg: localStorage.get('userMsg') ? localStorage.get('userMsg') : {},
        }
    },
    getters: {
        getUserMsg: (state) => {
            return state.userMsg
        }
    },
    actions: {
        setUserMsg(userMsg) {
            localStorage.set('userMsg', userMsg)
            localStorage.set('token', userMsg.token)
        }
    }
})
  • 接口配置使用axios
// src/api/axios.js
import axios from 'axios';
import localStorage from 'store';
import router from '../router';
const url = process.env.NODE_ENV === 'development' ? '/admin' : 'https://www.test.com';
const api = axios.create({
    baseURL: url,
    transformRequest: [
        function(data, headers) { //请求拦截 允许在向服务器发送前,修改请求数据
            if (data instanceof FormData) {
                return data;
            }
            if (headers['Content-Type'].indexOf('application/json') > -1) {
                return JSON.stringify(data);
            }
            let ret = '';
            for (let it in data) {
                ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
            }
            return ret;
        },
    ],
    headers: { // 修改请求头
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
    },
});
api.interceptors.response.use((response) => { // 对接口响应进行拦截
    if (response.data == 401) { // 登入过期跳转到登录页
        localStorage.clearAll();
        router.push('/login');
    }
    return response;
}, (error) => {
    return Promise.resolve({ // 对接口错误进行处理
        data: {
            code: error.response.status,
            message: error.message,
            data: error.response.data
        }
    });
});
let token = localStorage.get('token')
if (token) { // 设置默认token 在刷新页面时设置
    api.defaults.headers.common['token'] = token;
}
export default api;

// src/api/baseApi.js
import axios from './axios'
export default {
    /**
     * 登入
     * @param {*} phone 手机
     * @param {*} verifCode 验证码
     * @returns 
     */
    login(phone, verifCode) {
        return new Promise((resolve, reject) => {
            axios({
                url: "/login",
                method: "post",
                data: { phone, verifCode }
            }).then(res => {
                resolve(res.data)
            })
        })
    },
}

// src/api/index.js
import BaseApi from "./baseApi";
export default { BaseApi };

// 在需要使用接口的文件中
<script setup>
import api from '@/api'
let res = await api.BaseApi.login(phone.value, verifCode.value)
if (res.code === 200) {
    // 成功
} else {
    // 失败
}
</script>
  • main.js配置
import { createApp } from 'vue';
import 'element-plus/dist/index.css'; // 引用ele的css基础样式
import App from './App.vue';
import router from './router'; // 挂载路由
import { createPinia } from 'pinia'; // 挂载pinia
import ElementPlus from 'element-plus'; // 挂载ele
import locale from 'element-plus/lib/locale/lang/zh-cn'; // 引用ele中文包
import { Container } from '@/components/public'; // 引用组件
const app = createApp(App).use(router).use(ElementPlus, { locale }).use(createPinia());
app.component('Container', Container); // 注册全局组件
app.mount('#app')

最后

一个简单的vue3+vite的项目的基础的主要配置已经完成了,接下来可以开心的撸页面去了,这篇文章中的所有相关代码已经上传github了。戳这里 vueBase