VUE 从零开始搭建企业级后台管理

创建项目

js 复制代码
// 使用vite创建项目, 并指定模板为vue
npm create vite@latest vue-app -- --template vue
// 执行上面命令后,控制台会输出下面三句话
cd vue-app // 进行项目文件夹
npm install // 安装项目依赖 网络不好的可以尝试使用 yarn 或 cnpm
npm run dev // 运行项目

执行完以上命令后 你将会看到一下页面

下面们来看看项目的代码, 在编辑器里打开后会呈现如下的文件目录

其中我们最关心的红色部分

  • node_modules里存放的全是项目依赖 通过npm install安装的都会在里面,
  • public存放的是静态文件 如 index.html 图片等文件
  • assets里放静态资源 图片 图标 等
  • components 存放的是我们项目里的vue 组件
  • app.vue 项目跟组件 最先加载的组件
  • main.js 项目入口文件 主要用于启动插件
  • vite.config.js vite的配置 项目打包配置时有用

下面我们来看项目入口文件,和根组件

main.js

app.vue

使用路由

首先我们安装路由

js 复制代码
npm install vue-router@4 //网络不好可以使用 yarn add vue-router@4 或 cnpm 

使用路由

  • 在scr下创建views文件夹, 在views下创建两个vue文件, 就是路由跳转匹配的页面
  • 首先在src文件夹下创建router文件夹, 然后再router 文件夹下创建 index.js
  • 在index.js编写路由规则 在文件里我们写了两个路由 / 和 /about 并使用createWebHashHistory方式加载路由 这里我我们使用了 import.meta.glob('../views/**/*.vue')的方式去加载组件
js 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'

const routerFile =  import.meta.glob('../views/**/*.vue')
const routes = [
    {
        path: "/",
        component: () => routerFile['../views/home.vue']()
    },
     {
        path: "/about",
        component: () => routerFile['../views/about.vue']()
    }
]

// 导出router 在main里给vue使用
export const router = createRouter({
    history: createWebHashHistory(),
    routes
})

expoer funtion setupRouter(app){
    app.use(router)
    router.isReady()
}
  • 在main.js 里使用路由
js 复制代码
import { createApp } from 'vue' 
import { setupRouter } from './router/index.js' // 引入 router 导出
import './style.css'
import App from './App.vue'


const app = createApp(App)
setupRouter(app)
app.mount("#app")
  • 在app跟组件里来接受路由
js 复制代码
<template>
  <p>
    <router-link to="/">Home</router-link>
    /
    <router-link to="/about">About</router-link>
  </p>

  <router-view></router-view>
</template>

<script setup>

</script>

以上就实现了最简单的路由匹配, 让我们来查一下效果吧

使用antd

安装antd

js 复制代码
npm install ant-design-vue@4.x --save
// 或者
yarn add ant-design-vue@4.x

如何使用,在main.js里引入 并use(antd), 这里是全局注册,要按需注册,需引入所需组件使用即可

js 复制代码
 import { createApp } from 'vue'; 
 import Antd from 'ant-design-vue'; 
 import App from './App'; 
 import 'ant-design-vue/dist/reset.css'; 
 
 const app = createApp(App); 
 app.use(Antd)
 app.mount('#app');

更多antd 用法请参考antdv官网 各种组件用法例示都有

antd layout布局

1 首先写出layout 组件, 在components下 新建layout文件夹, 创建 index.js 以及两个组件 登录layout 和 main layout 代码如下

index.js

js 复制代码
import  MainLayout  from './mainLayout.vue'
import  LoginLayout  from './loginLayout.vue'

export function setupLayout(app){
    app.component('MainLayout', MainLayout)
    app.component('LoginLayout', LoginLayout)
}

mainLayout.vue

js 复制代码
<template>
  <a-layout style="height: 100vh;">
      <a-layout-header :style="headerStyle">顶部区域</a-layout-header>
      <a-layout>
        <a-layout-sider :style="siderStyle">菜单区域</a-layout-sider>
        <a-layout-content :style="contentStyle">
           <router-view></router-view>
        </a-layout-content>
      </a-layout>
      <a-layout-footer :style="footerStyle">底部区域</a-layout-footer>
  </a-layout>
</template>

loginLayout.vue

js 复制代码
<template>
    <a-layout class="main-container">
        <router-view></router-view>
    </a-layout>
</template>

完成以上步骤后 在main.js 里引入并使用 layout 代码如下

js 复制代码
import { createApp } from 'vue'  // 引入vue启动函数
import { router } from './router/index.js'
import Antd from 'ant-design-vue';
import { setupLayout } from './components/layout/index.js'
import './style.css'
import 'ant-design-vue/dist/reset.css';
// 引入App组件
import App from './App.vue'


const app = createApp(App)
// 使用引入的layout
setupLayout(app)  
app.use(router)
app.use(Antd)
app.mount("#app")

下面还需要配置两处地方,才可以产生效果 app.vue 和 router下面的index.js

app.vue 修改后

js 复制代码
<template>
  <component :is="componentId">
    <router-view></router-view>
  </component>

</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router';

const route = useRoute()
const componentId = computed(() => {
    return route.meta.layout || 'div'; // 默认情况下使用一个 div 包裹
});
</script>

router/ index.js

js 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'

const routeFiles = import.meta.glob('../views/**/*.vue')

const routes = [
    {
        path: "/",
        name: 'index',
        meta:{
            layout: 'MainLayout'
         },
        component:() => routeFiles['../views/home.vue']()
       
    },
    {
        path: "/login",
        name: 'login',
        meta:{
            layout: 'LoginLayout'
         },
        component:() => routeFiles['../views/login/index.vue']()
       
    },

    {
        path: '/about',
        name: 'about',
        meta:{
            layout: 'MainLayout'
         },
        component:() => routeFiles['../views/about.vue']()
      
    }
]

export const router = createRouter({
    history :createWebHashHistory(),
    routes
})

效果: 通过加载不同的路由就实现了 加载不同的layout

http://localhost:5173/#/

http://localhost:5173/#/login

使用pinia

安装pinia

js 复制代码
npm install pinia
或者
yarn add pinia

在src文件夹下创建 store, 在store下创建index.js 和 modules文件夹,在modules下创建 index.js 和user文件夹然后在 user下在创建user.js

store下的index.js 创建pinia 导入modules下的store

js 复制代码
import { createPinia } from "pinia";

const store = createPinia()

export function setupStore(app) {
  app.use(store)
}

export * from './modules'

modules下的index.js 导出store 如果后续有多少store 就导出多少

js 复制代码
export * from './user/user'

user.js这里创建了一个存储token的store

js 复制代码
import { defineStore } from "pinia"

const LOCAL_NAME = 'token'

function getToken(){
    return localStorage.getItem(LOCAL_NAME)
}

function setToken(token){
    localStorage.setItem(LOCAL_NAME, token)
}
export const userStore = defineStore("user", {
    state: () => getToken(),
    getters: {
        getToken: (state) => state.token
    },
    actions: {
        setToken(token){
            this.token = token
            setToken(token)
        }
    }
})

在main.js里注册store

js 复制代码
import { setupStore } from './store/index.js'
const app = createApp(App)
setupStore(app);
app.mount("#app")

使用

js 复制代码
<template>
    <div>
        我是home页面
        <a-button type="primary" @click="setToken">存储token</a-button>
        <a-button type="primary" @click="getToken">获取token</a-button>
        {{ T }}
    </div>
</template>

<script setup>
import { ref } from 'vue'
import { useUserStore } from '../store/index.js'

const T = ref("")
const userStore = useUserStore()

const setToken = () => {
    userStore.setToken("122121")
}

const getToken = () =>{
    T.value = userStore.getToken
}
</script>

登录页面

html

js 复制代码
<template>
    <div class="login">
         <div class="login-header">
            <span>vue后台管理系统</span>
         </div>
         <div class="login-conent">
            <div class="login-conent-form">
                <a-form
                    :model="formState"
                    name="basic"
                    :label-col="{ span: 4 }"
                    :wrapper-col="{ span: 20 }"
                    autocomplete="off"
                    @finish="onFinish"
                >
                    <a-form-item
                    label="用户名"
                    name="username"
                    :rules="[{ required: true, message: 'Please input your username!' }]"
                    >
                    <a-input v-model:value="formState.username" />
                    </a-form-item>

                    <a-form-item
                    label="密码"
                    name="password"
                    :rules="[{ required: true, message: 'Please input your password!' }]"
                    >
                    <a-input-password v-model:value="formState.password" />
                    </a-form-item>

                 
                    <a-form-item>
                        <a-button type="primary" html-type="submit">登录</a-button>
                    </a-form-item>
                </a-form>
            </div>
         </div>

         <div class="login-footer">

</div>
    </div>
</template>

vue

js 复制代码
import { reactive, nextTick} from 'vue';
import { router } from '../../router/index'
import { useUserStore } from '../../store/index'
interface FormState {
  username: string;
  password: string;
  remember: boolean;
}
const formState = reactive<FormState>({
  username: 'admin',
  password: 'admin',
  remember: true,
});

const userStore = useUserStore()

const onFinish = async (values: any) => {
    // 调用登录接口 
    // 登录成功后 处理用户token 用户信息 后并路由跳转 
    await userStore.setToken("token")
    nextTick(() =>{
        router.push("/")
    })
   
};

beforeEach 判断用户是否登录 如果登录 存在用户token 直接进入页面 如果未登录 进入登录页面 在router文件夹下新建 guard.js 代码如下

js 复制代码
import { message } from 'ant-design-vue'
import { useUserStore } from '../store/index'
import { store } from '../store/index'

const passPath = ["/login"]
const userStore = useUserStore(store)


export function setupPageGuard(router){
    router.beforeEach( async (to, form, next) =>{
        if(passPath.includes(to.path)){
             next()
        }else{
           if(!userStore.getToken){
             message.success("请先登录")
             next('/login')
           }else{
            next()
           }
        }
    }) 
}

使用guard.js

js 复制代码
import { setupPageGuard } from './guard'
setupPageGuard(router)

这样就完成登录了

相关推荐
be or not to be6 分钟前
HTML入门系列:从图片到表单,再到音视频的完整实践
前端·html·音视频
90后的晨仔43 分钟前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端
沿着路走到底1 小时前
JS事件循环
java·前端·javascript
子春一22 小时前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶2 小时前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn3 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪3 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ3 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied3 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一23 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter