美文网首页
开发一个后台管理系统的主框架页面(登录、主界面、子界面)

开发一个后台管理系统的主框架页面(登录、主界面、子界面)

作者: _Bell_ | 来源:发表于2023-09-07 14:13 被阅读0次

    登录

    1. 找到 src/router/index.js 路由文件,添加登录路由代码:
    {
      path: '/login',
      component: (resolve) => require(['@/views/login.vue'], resolve)
    }
    
    2. 在 src/views 目录下新增 login.vue 文件,内容如下:
    <template>
      <div class="login-bg">
        <div class="login-box">
          <h2 class="login-tit">My Vue2</h2>
          <el-form :model="formData" @keyup.enter.native="submit">
            <el-form-item prop="userName">
              <el-input v-model="formData.userName" clearable prefix-icon="el-icon-user" placeholder="请输入用户名" autofocus></el-input>
            </el-form-item>
            <el-form-item prop="password">
              <el-input v-model="formData.password" clearable prefix-icon="el-icon-unlock" placeholder="请输入密码" show-password></el-input>
            </el-form-item>
            <p>用户名密码随意填写即可!</p>
            <el-button class="btn-submit" type="primary" @click="submit" :loading="loading">登 录</el-button>
          </el-form>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          loading: false,
          // 表单相关
          formData: {
            userName: '',
            password: ''
          }
        }
      },
      mounted() {
      },
      methods: {
        /**
         * 登录
         */
        submit() {
          this.loading = true
          this.$store.commit('SET_USER', { userName: this.formData.userName })
          this.$router.replace('/home')
        }
      }
    }
    </script>
    <style lang="less" scoped>
    .login-bg {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background: #f7f7f7;
    }
    .login-box {
      width: 400px;
      padding: 20px;
      background: #fff;
      border-radius: 8px;
      .login-tit {
        margin-bottom: 20px;
        text-align: center;
      }
      .btn-submit {
        width: 100%;
      }
    }
    </style>
    
    

    以上代码实现了一个简单的登录页面,在表单中输入用户名和密码后,点击登录按钮可以进行登录操作,并跳转到系统主页。

    3. 定义表单验证文件

    src/assets/scripts目录下新增一个名为validate.js的文件,内容如下:

    export default {
      // 非空 输入框
      RI: { required: true, message: '请输入' },
      // 非空 选择器
      RS: { required: true, message: '请选择' },
      // 不以空格开头或结尾
      space: { pattern: /^[^\s]+(\s+[^\s]+)*$/, message: '不以空格开头或结尾' }
    }
    

    以上代码是一个验证规则的定义文件,通过导出一个对象来提供几个常用的验证规则。
    这样我们就能将整个应用的验证规则都写在这个文件进行统一管理,避免后期维护时在页面组件中进行修改。

    4. 在登录中使用定义的验证规则

    打开之前新建的login.vue文件,在script中添加引入验证文件代码:

    import V from '@/assets/scripts/validate'
    
    export default {
      data() {
        return {
          V
        }
      }
    }
    

    template模板中,将规则绑定到表单项中:

    <el-form-item prop="userName" :rules="[V.RI, V.space]">
    ···
    </el-form-item>
    <el-form-item prop="password" :rules="[V.RI], V.space">
    ···
    </el-form-item>
    

    提交时调用验证:

    submit() {
      this.$refs.formData.validate((valid) => {
        if (valid) {
          this.loading = true
          this.$store.commit('SET_USER', { userName: this.formData.userName })
          this.$router.replace('/home')
        }
      })
    }
    

    login.vue文件修改完成后的完整内容如下:

    <template>
      <div class="login-bg">
        <div class="login-box">
          <h2 class="login-tit">My Vue2</h2>
          <el-form :model="formData" ref="formData" @keyup.enter.native="submit">
            <el-form-item prop="userName" :rules="[V.RI, V.space]">
              <el-input v-model="formData.userName" clearable prefix-icon="el-icon-user" placeholder="请输入用户名" autofocus></el-input>
            </el-form-item>
            <el-form-item prop="password" :rules="[V.RI, V.space]">
              <el-input v-model="formData.password" clearable prefix-icon="el-icon-unlock" placeholder="请输入密码" show-password></el-input>
            </el-form-item>
            <p>用户名密码随意填写即可!</p>
            <el-button class="btn-submit" type="primary" @click="submit" :loading="loading">登 录</el-button>
          </el-form>
        </div>
      </div>
    </template>
    
    <script>
    import V from '@/assets/scripts/validate'
    
    export default {
      data() {
        return {
          V,
          loading: false,
          // 表单相关
          formData: {
            userName: '',
            password: ''
          }
        }
      },
      mounted() {
      },
      methods: {
        /**
         * 登录
         */
        submit() {
          this.$refs.formData.validate((valid) => {
            if (valid) {
              this.loading = true
              this.$store.commit('SET_USER', { userName: this.formData.userName })
              this.$router.replace('/home')
            }
          })
        }
      }
    }
    </script>
    <style lang="less" scoped>
    .login-bg {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background: #f7f7f7;
    }
    .login-box {
      width: 400px;
      padding: 20px;
      background: #fff;
      border-radius: 8px;
      .login-tit {
        margin-bottom: 20px;
        text-align: center;
      }
      .btn-submit {
        width: 100%;
      }
    }
    </style>
    

    这样我们一个基础的登录就完成了,其中包括了:进入页面自动聚焦到用户名输入框、密码框内容可见切换、登录表单中输入框聚焦时回车键触发提交事件、表单验证和验证成功后将输入的用户名放入Vuex用户对象中并跳转到首页。

    主子界面路由嵌套

    1. 在src/components目录中新建一个目录layout并在目录中新建一个名为wrap.vue的文件,内容如下:
    <template>
      <div class="wrapper">
        <keep-alive>
          <router-view v-if="$route.meta.keepAlive"></router-view>
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
        }
      },
      mounted() {
      },
      methods: {
      }
    }
    </script>
    
    <style lang="less" scoped>
    </style>
    

    <keep-alive> 是 Vue 中的一个内置组件,用于保留组件状态并缓存组件实例。它可以在组件切换时将组件保存在内存中,以便下次再使用时不需要重新渲染和初始化组件。

    在 Vue Router 配置中,可以通过嵌套多个 <router-view> 来构建复杂的页面布局。每个 <router-view> 将根据不同的路由匹配来渲染相应的组件内容,其中最外层 <router-view> 对应着根路由,而嵌套的 <router-view> 对应着子路由。
    这样我们就能通过了文件中的 <router-view> 匹配渲染子路由的组件内容,从而实现主子页面的嵌套效果。

    2. 新建首页页面组件

    src/views/目录中新增一个名为home的子目录,并在新目录下添加一个名为 index.vue 的文件,内容如下:

    <template>
      <div class="center">
        <h2>欢迎使用!</h2>
      </div>
    </template>
    <style lang="less" scoped>
      .center {
        display: grid;
        place-items: center;
        height: 100%;
      }
    </style>
    
    
    3. 配置路由

    src/router/目录中新增一个名为menus.js的子路由文件,内容如下:

    export default [
      {
        path: '/home',
        component: (resolve) => require(['@/views/home/index.vue'], resolve),
        meta: {
          keepAlive: true
        }
      },
      {
        path: '/one/two',
        component: (resolve) => require(['@/views/home/index.vue'], resolve)
      }
      // 其他菜单页面路由
    ]
    

    上述代码中 meta 对象中 keepAlive 属性用于设置 wrap.vue<keep-alive> 标签的缓存是否开启。

    找到src/router/index.js文件,引入wrap.vuemenus.js:

    import wrap from '@/components/layout/wrap.vue'
    import menusRouter from './menus' // 菜单路由
    

    将原来的/home路由配置代码改为由嵌套的结构,并将子页面路由嵌套进去,内容如下:

    {
      path: '/',
      component: wrap,
      children: menusRouter
    }
    

    src/router/index.js 路由文件修改完成后的完整代码内容如下:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import wrap from '@/components/layout/wrap.vue'
    import menusRouter from './menus' // 菜单路由
    
    Vue.use(VueRouter)
    
    const pages = [
      {
        path: '/',
        component: wrap,
        children: menusRouter
      },
      {
        path: '/login',
        component: (resolve) => require(['@/views/login.vue'], resolve)
      },
      {
        path: '/errorPage/404',
        component: (resolve) => require(['@/views/404.vue'], resolve)
      }
    ]
    
    const router = new VueRouter({
      routes: [
        // 默认路由
        {
          path: '/',
          redirect: '/home'
        },
        // 页面路由
        ...pages,
        // 没有匹配的路由重定向到404页面
        {
          path: '*',
          redirect: '/errorPage/404'
        }
      ]
    })
    
    // 路由跳转前
    router.beforeEach((to, from, next) => {
      // 可用于拦截导航并执行一些操作,例如验证用户身份、权限控制等。
      next()
    })
    
    // 路由跳转后
    router.afterEach((to, from) => {
      window.scrollTo(0, 0) // 每次路由改变滚动条都回到顶部
    })
    
    export default router
    

    这样一个基本的主子界面路由嵌套关系就完成了,之后我们只需要在wrap.vue中添加主界面的基本功能:菜单栏、头部导航栏、子界面显示区域。

    主子界面的基本功能和样式布局

    菜单栏

    菜单部分我们当前应用做常规的左侧菜单栏。

    1. 在layout目录中新建一个名为menu-tree.vue的无限菜单组件文件,内容如下:
    <template>
      <div class="menu-tree">
        <template v-for="item in menuList">
          <el-submenu :key="item.path" :index="item.path" v-if="item.children && item.children.length > 0">
            <template slot="title">
              <i :class="item.icon"></i>
              <span slot="title">{{item.title}}</span>
            </template>
            <!-- 组件自调用 -->
            <MenuTree :menuList="item.children"></MenuTree>
          </el-submenu>
          <el-menu-item :key="item.path" :index="item.path" v-else>
            <i :class="item.icon"></i>
            <span slot="title">{{item.title}}</span>
          </el-menu-item>
        </template>
      </div>
    </template>
    
    <script>
    export default {
      name: 'MenuTree', // name 必须写用于组件自调用
      props: {
        // 菜单列表
        menuList: {
          type: Array,
          default: () => []
        }
      }
    }
    </script>
    
    2. 在layout目录中新建一个名为menu.vue的菜单组件文件,并在其中使用无限菜单组件,内容如下:
    <template>
      <div class="menu-box" :class="{'menu-collapse': isCollapse}">
        <i class="collapse-icon" :class="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'" @click="isCollapse = !isCollapse"></i>
        <div class="menu-logo">
          <img class="logo-img" src="@img/logo.png" alt="logo">
          <span class="logo-name">My Vue2</span>
        </div>
        <el-scrollbar>
          <el-menu
            :default-active="$route.path"
            :collapse="isCollapse"
            :collapse-transition="false"
            unique-opened
            router
            background-color="#202123"
            text-color="#fff"
            active-text-color="#409EFF"
          >
            <MenuTree :menuList="menuList" />
          </el-menu>
        </el-scrollbar>
      </div>
    </template>
    
    <script>
    import MenuTree from './menu-tree.vue'
    
    export default {
      components: { MenuTree }, // 组件
      data() {
        return {
          isCollapse: false,
          menuList: [
            {
              path: '/home',
              title: '首页',
              icon: 'el-icon-s-home'
            },
            {
              path: '/one',
              title: '一级页面',
              icon: 'el-icon-menu',
              children: [
                {
                  path: '/one/two',
                  title: '二级页面'
                }
              ]
            }
          ]
        }
      },
      methods: {
      }
    }
    </script>
    
    <style lang="less" scoped>
    .menu-box {
      position: relative;
      flex-shrink: 0;
      width: 300px;
      background: #202123;
      transition: width .3s;
      &.menu-collapse {
        width: 64px;
        .logo-name {
          display: none;
        }
        /deep/ .el-submenu__title span {
          display: none;
        }
      }
      .collapse-icon {
        position: absolute;
        right: -30px;
        top: 15px;
        font-size: 30px;
        color: #fff;
      }
      .menu-logo {
        display: flex;
        align-items: center;
        padding: 0 15px;
        height: 60px;
        color: #fff;
        font-size: 20px;
        white-space: nowrap;
        overflow: hidden;
        .logo-img {
          margin-right: 10px;
          height: 30px;
        }
      }
      .el-scrollbar {
        height: calc(100% - 60px);
        /deep/ .el-scrollbar__wrap {
          overflow-x: hidden;
        }
      }
      .el-menu {
        border: 0;
      }
    }
    </style>
    
    3. 在wrap.vue中引用组件并使用:

    引入菜单组件

    import Menu from './menu.vue'
    

    注册组件

    components: { Menu }, // 组件
    

    template中使用组件

    <Menu/>
    

    wrap.vue修改后的完整内容如下:

    <template>
      <div class="wrapper">
        <Menu />
        <keep-alive>
          <router-view v-if="$route.meta.keepAlive"></router-view>
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view>
      </div>
    </template>
    
    <script>
    import Menu from './menu.vue'
    
    export default {
      components: { Menu }, // 组件
      data() {
        return {
        }
      },
      mounted() {
      },
      methods: {
      }
    }
    </script>
    
    <style lang="less" scoped>
    </style>
    

    头部导航栏

    1. 在 layout 目录下新建一个名为 header.vue 的头部导航栏组件,内容如下:
    <template>
      <div class="header-box">
      </div>
    </template>
    
    <script>
    export default {
      data() {
      },
      methods: {
      }
    }
    </script>
    
    <style lang="less" scoped>
    </style>
    
    2. 在wrap.vue中引用组件并使用:

    引入菜单组件

    import Header from './header.vue'
    

    注册组件

    components: { Header }, // 组件
    

    template中使用组件,并修改菜单组件、头部组件、子界面容器的代码结构:

    <template>
      <div class="wrapper">
        <Menu />
        <div class="header-subpage-content">
          <Header />
          <div class="subpage-content">
            <keep-alive>
              <router-view v-if="$route.meta.keepAlive"></router-view>
            </keep-alive>
            <router-view v-if="!$route.meta.keepAlive"></router-view>
          </div>
        </div>
      </div>
    </template>
    

    添加主子界面布局样式

    .wrapper {
      display: flex;
      width: 100%;
      height: 100vh;
      .header-subpage-content {
        display: flex;
        flex-direction: column;
        width: 100%;
        .subpage-content {
          height: 100%;
        }
      }
    }
    

    wrap.vue修改后的完整内容如下:

    <template>
      <div class="wrapper">
        <Menu />
        <div class="header-subpage-content">
          <Header />
          <div class="subpage-content">
            <keep-alive>
              <router-view v-if="$route.meta.keepAlive"></router-view>
            </keep-alive>
            <router-view v-if="!$route.meta.keepAlive"></router-view>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import Menu from './menu.vue'
    import Header from './header.vue'
    
    export default {
      components: { Menu, Header }, // 组件
      data() {
        return {
        }
      },
      mounted() {
      },
      methods: {
      }
    }
    </script>
    
    <style lang="less" scoped>
      .wrapper {
        display: flex;
        width: 100%;
        height: 100vh;
        .header-subpage-content {
          display: flex;
          flex-direction: column;
          width: 100%;
          .subpage-content {
            height: 100%;
          }
        }
      }
    </style>
    
    3. 用户基本操作模块(用户头像、用户名、退出登录)

    header.vue 中内容替换为以下内容:

    <template>
      <div class="header-box">
        <el-dropdown class="user-dropdown" @command="handleUser">
          <img class="user-pic" src="@img/pic.png" />
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item disabled>{{ $store.getters.GET_USER.userName }}</el-dropdown-item>
            <el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
        }
      },
      methods: {
        /**
         * 用户相关操作
         * @param {String} functionName 函数名称
         */
        handleUser(functionName) {
          this[functionName]()
        },
        /**
         * 退出登录
         */
        logout() {
          this.$router.replace('/login')
        }
      }
    }
    </script>
    
    <style lang="less" scoped>
      .header-box {
        min-height: 60px;
        color: #fff;
        background: #202123;
        .user-dropdown {
          float: right;
          display: flex;
          align-items: center;
          margin-right: 10px;
          height: 100%;
          color: #fff;
          cursor: pointer;
          .user-pic {
            width: 40px;
            height: 40px;
          }
        }
      }
    </style>
    

    到这里整个后台管理系统的基本主框架页面就完成了,后续再根据自己的添加或修改内容。


    框架搭建整体流程

    点击下载步骤 1-7 配置完成的完整 Demo


    本框架更多功能 Demo 下载

    相关文章

      网友评论

          本文标题:开发一个后台管理系统的主框架页面(登录、主界面、子界面)

          本文链接:https://www.haomeiwen.com/subject/pehrmdtx.html