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)

这样就完成登录了

相关推荐
测试界柠檬2 分钟前
面试真题 | web自动化关闭浏览器,quit()和close()的区别
前端·自动化测试·软件测试·功能测试·程序人生·面试·自动化
多多*2 分钟前
OJ在线评测系统 登录页面开发 前端后端联调实现全栈开发
linux·服务器·前端·ubuntu·docker·前端框架
2301_801074153 分钟前
TypeScript异常处理
前端·javascript·typescript
ᅠᅠᅠ@4 分钟前
异常枚举;
开发语言·javascript·ecmascript
小阿飞_4 分钟前
报错合计-1
前端
caperxi6 分钟前
前端开发中的防抖与节流
前端·javascript·html
霸气小男6 分钟前
react + antDesign封装图片预览组件(支持多张图片)
前端·react.js
susu10830189117 分钟前
前端css样式覆盖
前端·css
学习路上的小刘8 分钟前
vue h5 蓝牙连接 webBluetooth API
前端·javascript·vue.js
&白帝&8 分钟前
vue3常用的组件间通信
前端·javascript·vue.js