vue纯前端设计动态路由+页面架构

前言

好久没有更新博客了,今天就写一下vue脚手架+antd如何架构一个后台管理系统页面,本来是想弄微前端的但是想想还是算了,不过你熟了的话,可以使用微前端进行架构,基于主体布局不变嵌入微前端。

上图

还行,不过有很多细节没有处理好。不过作为一个参考模型是足够了,我的写偏向简单,看一遍就会了

开始

这里我就主要讲两块(页面架构、路由设计)

App.vue

ps:这里添加一个路由组件(一级页面需要)

<template>
  <div id="app">
     <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      
    }
  },
  mounted() {
    
  },
  created() {
   
  },
  methods: {
    
  }
}
</script>

<style>

</style>

layout.vue

ps:在tab标签下添加一个路由组件(二级页面需要)

<template>
  <div>
      <a-layout id="components-layout-demo-top-side">
        <!-- 头部页 -->
        <a-layout-header class="header">
          <div class="logo" />
          <a-menu
            theme="dark"
            mode="horizontal"
            :default-selected-keys="headerSelectMenu"
            :style="{ lineHeight: '64px' }"
            @click="changHeaderMenu"
          >
            <a-menu-item v-for="item in headerMenu" :key="item['id']">
              {{item.name}}
            </a-menu-item>
          </a-menu>
        </a-layout-header>
        <!-- 主体页 -->
        <a-layout-content style="padding: 0 50px">
          <!-- 面包屑 -->
          <!-- <a-breadcrumb style="margin: 16px 0">
            <a-breadcrumb-item>首页</a-breadcrumb-item>
            <a-breadcrumb-item>测试</a-breadcrumb-item>
            <a-breadcrumb-item>测试页</a-breadcrumb-item>
          </a-breadcrumb> -->
          <!-- 左边导航栏 -->
          <a-layout style="padding: 24px 0; background: #fff">
            <a-layout-sider width="200" style="background: #fff">
              <!-- :default-open-keys="leftOpenSelectMenu" -->
              <!-- :default-selected-keys="leftSelectMenu" -->
              <a-menu
                mode="inline"
                style="height: 100%"
                :default-open-keys="leftOpenSelectMenu" 
                :default-selected-keys="leftSelectMenu"
                @click="changLeftMenu"
              >
                <a-sub-menu v-for="leftItem in leftMenu" :key="leftItem['id']">
                  <span slot="title"><a-icon type="user" />{{leftItem['name']}}</span>
                  <a-menu-item v-for="leftCholdrenItem in leftItem['children']" :key="leftCholdrenItem['id']">
                    {{leftCholdrenItem['name']}}
                  </a-menu-item>
                </a-sub-menu>
              </a-menu>
            </a-layout-sider>
            <!-- 页面内容显示 -->
            <a-layout-content :style="{ padding: '0 24px', minHeight: '280px' }">
              <!-- 页面标签 -->
              <a-tabs v-model="activeKey" type="editable-card" @edit="onEdit" :hideAdd="true" @change="changTab">
                <a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title" :closable="pane.closable">
                  <!-- {{ pane.content }} -->
                  
                  <keep-alive>
                      <router-view></router-view>
                  </keep-alive> 

                </a-tab-pane>
              </a-tabs>
            </a-layout-content>
          </a-layout>
        </a-layout-content>
        <!-- 底部页 -->
        <a-layout-footer style="text-align: center">
          Ant Design ©2018 Created by Ant UED
        </a-layout-footer>
      </a-layout>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      activeKey: [],
      panes: [],

      headerSelectMenu: ['1'],
      headerMenu: [
        {
          name: '头部导航1',
          router: '',
          id: "1"
        },
        {
          name: '头部导航2',
          router: '',
          id: "2"
        }
      ],

      leftMenu: [],

      leftOpenSelectMenu: [],
      leftSelectMenu: [],
      

      leftMenuOne: [
        {
          name: '头部导航栏1',
          router: '',
          id: "1",
          children: [
            {
              name: '头部导航栏1-1',
              router: '/',
              id: "1-1"
            },
            {
              name: '头部导航栏1-2',
              router: '/test1',
              id: "1-2"
            }
          ]
        },
      ],
      leftMenuTwo: [
        {
          name: '头部导航栏2',
          router: '',
          id: "2",
          children: [
            {
              name: '头部导航栏2-1',
              router: '/test3',
              id: "2-1"
            },
            {
              name: '头部导航栏2-2',
              router: '/test4',
              id: "2-2"
            }
          ]
        },
        {
          name: '用户模块',
          router: '',
          id: "3",
          children: [
            {
              name: '用户列表',
              router: '/user',
              id: "3-1"
            }
          ]
        },
      ]
    }
  },
  mounted() {
    
  },
  created() {
    this.leftMenu = this.leftMenuOne
    this.leftSelectMenu = ['1-1']
    this.leftOpenSelectMenu = ['1']
    // { title: '头部导航栏1-2', content: 'Content of Tab 2', key: '1-2', closable: false }
    this.panes = [
      { title: '头部导航栏1-1', content: 'Content of Tab 1', key: '1-1', closable: false}
    ];
    this.activeKey = "1-1"
  },
  methods: {
    changTab(item) {

      // 头部导航栏1  点击 到头部导航栏2  tab标签有导航栏1的页面点击不过去
      
      this.leftSelectMenu = [item]

      console.log(item)
      let keyArr = item.split("-")

      console.log(keyArr)

      let keyFatherMenu = {}
      this.leftMenu.forEach((fatherMenuItem) => {
        if (fatherMenuItem['id'] == keyArr[0].toString()) {
          keyFatherMenu = fatherMenuItem
        }
      })
      console.log(keyFatherMenu)
      let addMenuObj = {}

      for(let j =1 ; j < keyArr.length; j ++) {
        let keyItem = keyArr[j]
        console.log(keyItem)
        if ('children' in keyFatherMenu) {
          keyFatherMenu['children'].forEach((childrenMenuItem) => {
            if (childrenMenuItem['id'] == keyArr[0] + '-' +keyItem) {
              addMenuObj = childrenMenuItem
              console.log(addMenuObj)
            }
          })
        }
      }

      this.$router.push({path:addMenuObj['router'], params:{}})
    },
    callback(key) {
      console.log(key);
    },
    onEdit(targetKey, action) {
      this[action](targetKey);
    },
    remove(targetKey) {
      let activeKey = this.activeKey;
      let lastIndex;
      this.panes.forEach((pane, i) => {
        if (pane.key === targetKey) {
          lastIndex = i - 1;
        }
      });
      const panes = this.panes.filter(pane => pane.key !== targetKey);
      if (panes.length && activeKey === targetKey) {
        if (lastIndex >= 0) {
          activeKey = panes[lastIndex].key;
        } else {
          activeKey = panes[0].key;
        }
      }
      this.panes = panes;
      this.activeKey = activeKey;
    },

    changLeftMenu(item) {
      // console.log(item)

      for(let i=0; i < this.panes.length; i ++) {
        let panesItem = this.panes[i]
        if(panesItem['key'] == item['key']) {
          this.activeKey = item['key']

          let keyArr = item['key'].split("-")
          let keyFatherMenu = {}
          this.leftMenu.forEach((fatherMenuItem) => {
            if (fatherMenuItem['id'] ==keyArr[0]) {
              keyFatherMenu = fatherMenuItem
            }
          })
          // console.log(keyFatherMenu)
          let addMenuObj = {}

          for(let j =1 ; j < keyArr.length; j ++) {
            let keyItem = keyArr[j]
            // console.log(keyItem)
            if ('children' in keyFatherMenu) {
              keyFatherMenu['children'].forEach((childrenMenuItem) => {
                if (childrenMenuItem['id'] == keyArr[0] + '-' +keyItem) {
                  addMenuObj = childrenMenuItem
                  // console.log(addMenuObj)
                }
              })
            }
          }

          this.$router.push({path:addMenuObj['router'], params:{}})
          break
        } else {
          if (i == this.panes.length - 1) {
            // console.log("最后一个元素")
            // console.log(this.leftMenu)

            let keyArr = item['key'].split("-")
            let keyFatherMenu = {}
            this.leftMenu.forEach((fatherMenuItem) => {
              if (fatherMenuItem['id'] ==keyArr[0]) {
                keyFatherMenu = fatherMenuItem
              }
            })
            // console.log(keyFatherMenu)
            let addMenuObj = {}

            for(let j =1 ; j < keyArr.length; j ++) {
              let keyItem = keyArr[j]
              // console.log(keyItem)
              if ('children' in keyFatherMenu) {
                keyFatherMenu['children'].forEach((childrenMenuItem) => {
                  if (childrenMenuItem['id'] == keyArr[0] + '-' +keyItem) {
                    addMenuObj = childrenMenuItem
                    // console.log(addMenuObj)
                  }
                })
              }
            }

            // 显示关闭图标
            this.panes.forEach((panesItemTwo) => {
              panesItemTwo['closable'] = true
            })

            // 进行添加
            let newAddObj = { title: addMenuObj['name'], content: 'Content of Tab' + item['key'], key: item['key'], closable: false }
            // console.log(newAddObj)
            this.panes.push(newAddObj)
            // 选中当前添加标签
            this.activeKey = item['key']
            this.$router.push({path:addMenuObj['router'], params:{}})
            break
          }
        }
      }
    },

    changHeaderMenu(item) {
      console.log(item['key'])
      if(item['key'] == '1') {
        this.leftMenu = this.leftMenuOne
        this.leftSelectMenu = ['1-1']
        this.leftOpenSelectMenu = [item['key']]
        this.activeKey = "1-1"
      } else if(item['key'] == '2') {
        this.leftMenu = this.leftMenuTwo
        this.leftSelectMenu = ['2-1']
        this.leftOpenSelectMenu = [item['key']]
        this.activeKey = "2-1"
      }
    }
  }
}
</script>

<style>

#components-layout-demo-top-side .logo {
  width: 120px;
  height: 31px;
  background: rgba(255, 255, 255, 0.2);
  margin: 16px 28px 16px 0;
  float: left;
}

</style>

main.js

import Vue from 'vue'

import router from './routers/index'

import App from './App.vue'

import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';

Vue.use(Antd);


Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

路由文件

import Layout from "@/views/layout/index"

/**
 * auth true登录才能访问,false不需要登录
 * keepAlive true缓存,false不缓存
 */

// 默认路由
export default [
    {
        path: '/',
        component: Layout,
        children: [
            {
                path: '/', // 首页
                meta: { auth: false, keepAlive: false },
                component: resolve => require(['@/views/home/'], resolve)
            },
            {
                path: '/test', // 测试
                meta: { auth: false, keepAlive: false },
                component: resolve => require(['@/views/test/'], resolve)
            }
        ]
    },
    {
        path: '/login',
        component: resolve => require(['@/views/login/'], resolve),
        meta: { auth: false, keepAlive: false },
    },
    {
        path: "/404",
        component: resolve => require(['@/views/notFound/'], resolve),
    }
]

路由权限文件

import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './config'
import Layout from "@/views/layout/index"

const _import = require('./_import_' + process.env.NODE_ENV)

Vue.use(VueRouter)

let getApiRouter = [
    {
        path: '/',
        component: "layout",
        children: [
            {
                path: '/test1', // 测试1
                meta: { auth: false, keepAlive: false },
                component: "test1"
            },
            {
                path: '/test2', // 测试2
                meta: { auth: false, keepAlive: false },
                component: "test2"
            },
            {
                path: '/test3', // 测试3
                meta: { auth: false, keepAlive: false },
                component: "test3"
            },
            {
                path: '/test4', // 测试4
                meta: { auth: false, keepAlive: false },
                component: "test4"
            },
            {
                path: '/user', // 用户列表
                meta: { auth: false, keepAlive: false },
                component: "user"
            },
        ]
    },
    {
        path: '*',
        redirect: "/404"
    }
]

let sumRouter = null

// 路由配置
const router = new VueRouter({
    mode: 'history',
    base: __dirname,
    routes
})

router.beforeEach((to, from, next) => {
    console.log(to)
    console.log(from)
    if (!sumRouter) {
        // 处理路由
        let dynamicMenu = filterAsyncRouter(getApiRouter)
        // 动态添加路由
        sumRouter = routes.concat(dynamicMenu)
        router.addRoutes(sumRouter)
        next({ ...to, replace: true })
    }
    next()
})

function filterAsyncRouter(asyncRouterMap) {
    const accessedRouters = asyncRouterMap.filter((route) => {
        if (route.component) {
            if (route.component === 'layout') {
                route.component = Layout
            } else {
                route.component = _import(route.component)
            }
        }
        if (route.children && route.children.length) {
            route.children = filterAsyncRouter(route.children)
        }
        return true
    })
    return accessedRouters
}


export default router

其实也没啥好讲的~想看整体代码进到这个传送门

结束

总结~好像也没啥好总结的,也就那样。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
django vue系统架构设计与实现的过程主要包括以下几个方面。 首先,对系统的整体架构进行设计。根据需求分析,确定系统的模块划分和功能设计。可以使用Django作为后端框架,提供API接口和数据处理功能;使用Vue作为前端框架,负责页面展示和用户交互。同时,可以选择使用其他数据库、缓存等技术来支持系统的数据存储和性能优化。 其次,搭建后端环境。使用Django框架创建项目,并配置好相关的数据库、缓存、安全认证等环境。根据系统的模块划分,设计并实现相应的Django模型、视图和路由等。通过Django提供的ORM(对象关系映射)功能,与数据库进行交互和数据操作。 接着,搭建前端环境。使用Vue-cli等工具创建项目,并配置好相关的开发环境和依赖。根据需求设计页面的布局和组件,利用Vue提供的数据绑定和事件处理等功能,与后端API进行交互,实现页面的动态展示和用户交互。 然后,实现后端接口和前端交互。在后端使用Django的视图函数或基于类的视图,处理前端请求,并返回相应的数据。在前端利用axios等工具,发送HTTP请求并处理响应,与后端进行数据交互和页面刷新。可以使用JWT(Json Web Token)等认证技术来保护API接口的安全性。 最后,进行系统的测试和优化。通过单元测试、功能测试等手段,对系统的各个功能进行验证。根据测试结果,对系统进行bug修复和性能优化,提高系统的可靠性和稳定性。 综上所述,django vue系统架构设计与实现需要进行整体架构设计、后端环境搭建、前端环境搭建、后端接口和前端交互、系统的测试和优化等步骤,通过合理的划分和设计,将后端框架和前端框架有机结合,实现高效的系统功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

An_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值