文章目录

  • ⭐前言
  • 💖vue3系列文章
  • ⭐ 自动化配置路由
  • 💖引入vite版本自定义目录映射
  • 💖自动化读取文件下的路由
  • 💖main入口加载路由
  • 💖入口app.vue配置
  • 💖layout基础布局配置
  • 💖效果
  • ⭐总结
  • ⭐结束



前端vite+vue3——自动化配置路由布局_自动化

⭐前言

大家好,我是yma16,本文分享关于 前端vite+vue3——自动化配置路由布局。

背景

在inscode写了一个前端vite+vue3+js的项目,路由分配有点乱,

现在给这个项目做个优化,路由配置。

没有配置路由之前的前端界面。

前端vite+vue3——自动化配置路由布局_javascript_02


改造之后

前端vite+vue3——自动化配置路由布局_vue3_03

vite

Vite是一种基于公有链技术的快速、安全和可扩展的开源区块链项目。它旨在通过使用异步交易模型和基于状态的共识算法来提高区块链的性能和可扩展性。

Vite的发展可以追溯到2018年,当时Vite团队发布了Vite
TestNet,开发者和用户可以通过该测试网络体验Vite的功能和性能。随后,Vite于2019年底发布了Vite
MainNet,正式上线并开放给广大用户使用。

在Vite的发展过程中,团队不断进行技术改进和优化,以提高其性能和可扩展性。Vite采用了异步交易模型,即交易可以并行处理,提高了交易的速度和吞吐量。另外,Vite使用基于状态的共识算法,即通过状态机来决定交易的顺序和执行结果,这可以减少节点之间的通信和同步开销,提高网络的效率。

除了性能和可扩展性的优化,Vite还提供了一些特色功能,如原生支持智能合约和去中心化交易所(DEX)。Vite的智能合约是基于Solidity编写的,与以太坊的智能合约兼容,使开发者可以轻松迁移到Vite平台。而Vite的DEX允许用户直接在区块链上进行点对点的交易,无需信任任何第三方中介,提高了交易的安全性和可信度。

vue-router

vue-router是Vue.js官方的路由插件,用于实现前端路由。它可以实现单页应用中的页面跳转、嵌套路由、路由参数传递、路由守卫等功能。通过vue-router,可以根据不同的路由地址,动态地渲染不同的组件,实现页面的切换和更新。同时,vue-router还提供了一些API和导航守卫,可以在路由跳转前后做一些额外的操作,如权限验证、页面统计等。Vue.js官方推荐使用vue-router来管理前端路由。


⭐ 自动化配置路由

vue3前端自动化配置路由离不开vue-router的使用,主要时使用router进行加载vue文件

💖引入vite版本自定义目录映射

package.json

{
  "name": "vuejs-with-vite",
  "author": "yma16",
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview --port 4173"
  },
  "dependencies": {
    "ant-design-vue": "^3.2.17",
    "axios": "^1.2.2",
    "echarts": "^5.4.2",
    "guess": "^1.0.2",
    "html2canvas": "^1.4.1",
    "vue": "^3.2.37",
    "vue-router": "^4.2.5",
    "vuex": "^4.1.0"
  },
  "devDependencies": {
    "@types/node": "^18.19.6",
    "@vitejs/plugin-vue": "^4.0.0",
    "less": "^4.2.0",
    "prettier": "^3.2.2",
    "vite": "^4.0.0"
  },
  "license": "MIT"
}

vite.config.js配置@映射到src目录

import { defineConfig } from 'vite'
import { resolve } from "path";
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  // 打包相对路径
  base: './',
  server: {
    host: true,
  },
  resolve: {
    alias: {
      "@": resolve(__dirname, "src"),
    },
  },
  plugins: [vue()]
})

💖自动化读取文件下的路由

vite读取modules目录下的配置加入路由中

import * as VueRouter from "vue-router";


// import.meta.glob() 直接引入所有的模块 Vite 独有的功能
const modules = import.meta.glob('./modules/*.js', { eager: true });

const routeModuleList=[]

console.log('modules',modules)
// 加入到路由集合中
Object.keys(modules).forEach((key) => {
    
    const mod = modules[key].default || {};
    const modList = Array.isArray(mod) ? [...mod] : [mod];
    console.log('modList',modList)
    routeModuleList.push(...modList);
});



console.log('routeModuleList',routeModuleList)
const router = VueRouter.createRouter({
    // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
    history: VueRouter.createWebHashHistory(),
    routes: routeModuleList,
});
// 路由权限  beforeResolve

router.beforeResolve(async (to, from, next) => {
    next()
});
export default router;

路由文件modules/layout.js

// 基础路由
// @ts-ignore
import LAYOUT from '@/layout/index.vue'

export default {
    path: '/',
    name: 'Layout',
    component: LAYOUT,
    redirect: '/SearchGrade',
    meta: {
        orderNo: 1,
        icon: 'ion:grid-outline',
        title: 'vue3 平台',
    },
    children: [
        {
            path: 'SearchGrade',
            name: 'SearchGrade',
            component: () => import('@/components/SearchGrade.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: 'csdn查分',
            },
        },
        {
            path: 'GameChart',
            name: 'GameChart',
            component: () => import('@/components/GameChart.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: 'vue3赛道可视化',
            },
        },
        {
            path: 'Draw',
            name: 'Draw',
            component: () => import('@/components/draw/Draw.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: '抽奖',
            },
        },
        {
            path: 'Drag',
            name: 'Drag',
            component: () => import('@/components/drag/Drag.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: '拼图',
            },
        },
        {
            path: 'Commit',
            name: 'Commit',
            component: () => import('@/components/commit/Commit.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: '大模型分析评论',
            },
        },
        {
            path: 'visual',
            name: 'visual',
            component: () => import('@/components/visual/index.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: '2023编码可视化',
            },
        },
        {
            path: 'visualHtml',
            name: 'visualHtml',
            component: () => import('@/components/visualHtml/index.vue'),
            meta: {

                icon: 'ion:grid-outline',
                title: '可视化html',
            },
        }
    ],
};

目录结构如下

前端vite+vue3——自动化配置路由布局_vue3_04


路由配置

💖main入口加载路由

createApp加载定义的router

import { createApp } from 'vue'
import App from './App.vue'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
import './assets/main.css'
import Router from "./router/index.js";

createApp(App)
.use(Antd)
.use(Router)
.mount('#app')

配置文件

前端vite+vue3——自动化配置路由布局_vite_05

💖入口app.vue配置

app.vue的配置

<script setup>
  import { ref } from "vue";
  import zhCN from "ant-design-vue/es/locale/zh_CN";
  import dayjs from "dayjs";
  import "dayjs/locale/zh-cn";
  /** 下载图片 */
const downloadBase64 = (content, fileName) => {
  const base64ToBlob = function (code) {
    let parts = code.split(';base64,');
    let contentType = parts[0].split(':')[1];
    let raw = window.atob(parts[1]);
    let rawLength = raw.length;
    let uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], {
      type: contentType
    });
  };
  let aLink = document.createElement('a');
  let blob = base64ToBlob(content);
  aLink.download = fileName + '.png';
  aLink.href = URL.createObjectURL(blob);
  aLink.click();
};

// 截图
const shotAction = () => {
  html2canvas(document.getElementById('render-id'), {
    useCORS: true,
    proxy: 'inscode.csdn.net',
    allowTaint: true,
    scale: 2,
  }).then(function (canvas) {
    console.log('canvas', canvas)
    const base64 = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, '');
    const base64img = `data:image/png;base64,${base64}`;
    downloadBase64(base64img, state.current);
    // document.body.appendChild(canvas);
  });
}

  dayjs.locale("zh-cn");
  const locale = ref(zhCN);
</script>


<template>
  <!--  国际化配置-->
  <a-config-provider :locale="locale">
    <div id="app">
      <router-view/>
    </div>
  </a-config-provider>
</template>

<style scoped>
  #app{
    width: 100vw;
    height: 100vh;
    background-size: 100%;
    background: linear-gradient(rgba(38, 38, 38, 0.5), rgba(40,140,234, 0.6)), url("/static/img/previewFix.jpg") no-repeat center;
  }
</style>

💖layout基础布局配置

layout的vue页面配置

<script setup>
import {
    MenuUnfoldOutlined,
    MenuFoldOutlined,
} from "@ant-design/icons-vue";

import { reactive, onMounted } from "vue";
import { useRouter } from "vue-router";

//router
const router = useRouter();
const state = reactive({
    title: "vue3平台",
    openKeys: [],
    selectedKeys: [],
    collapsed: false,
    menuList: []
});


const collapeAction = () => {
    state.collapsed = !state.collapsed
}

const clickMenu = (menu, item) => {
    console.log('item', item)
    state.openKeys = [menu.key]
    state.selectedKeys = [menu.key]
    router.push({
        name: item.name
    })
}
//{ item, key, selectedKeys }
const selectMenu = (e) => {
    console.log(e)
};

const renderIcon = (icon) => {
    // return h(icon)
    return ''
}

onMounted(() => {
    console.log('router.current.value', router)

    const { routes } = router.options
    state.menuList = routes.reduce((pre, item) => {
        const isHiddenInLayout = item.meta.isHiddenInLayout
        if (!isHiddenInLayout) {
            const menuItem = {
                title: item.meta.title,
                path: item.path,
                key: item.name,
                name: item.name,
                icon: item.meta.icon,
                children: item.children.map(children => {
                    return {
                        title: children.meta.title,
                        path: children.path,
                        key: children.name,
                        name: children.name,
                    }
                })
            }
            pre.push(menuItem)
        }
        return pre
    }, [])
});
</script>

<template>
    <a-layout class="layout-container">
        <a-layout-sider v-model:collapsed="state.collapsed" :trigger="null" collapsible>
            <div class="logo" />
            <a-menu v-model:openKeys="state.openKeys" v-model:selectedKeys="state.selectedKeys" theme="dark" mode="inline"
                @select="selectMenu">
                <a-sub-menu v-for="menu in state.menuList" :key="menu.key">
                    <template #icon> {{ renderIcon(menu.icon) }}</template>
                    <template #title> <span>{{ menu.title }}</span></template>
                    <a-menu-item v-for="menuChild in menu.children" :key="menuChild.key" @click="clickMenu(menu, menuChild)">
                        {{ menuChild.title }}
                    </a-menu-item>
                </a-sub-menu>
            </a-menu>
        </a-layout-sider>
        <a-layout>
            <a-layout-header style="background: #ffffff; padding-left: 20px">
                <div style="display: flex">
                    <div style="width: 50%">
                        <menu-unfold-outlined v-if="state.collapsed" class="trigger" @click="collapeAction" />
                        <menu-fold-outlined v-else class="trigger" @click="collapeAction" />
                        {{ state.title }}
                    </div>
                </div>
            </a-layout-header>
            <a-layout-content class="content-box">
                <!--                    渲染子路由-->
                <router-view />
            </a-layout-content>
        </a-layout>
    </a-layout>
</template>

<style lang="less">
.layout-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.content-box {
    overflow: auto;
    max-height: calc(100vh - 64px);
    padding: 24px;
    background: #fff;
}

#components-layout-demo-custom-trigger .trigger {
    font-size: 18px;
    line-height: 64px;
    padding: 0 24px;
    cursor: pointer;
    transition: color 0.3s;
}

#components-layout-demo-custom-trigger .trigger:hover {
    color: #1890ff;
}

#components-layout-demo-custom-trigger .logo {
    height: 32px;
    background: rgba(255, 255, 255, 0.3);
    margin: 16px;
}

.site-layout .site-layout-background {
    background: #fff;
}

.main-container {
    width: 100%;
    height: 100%;
}
</style>

💖效果

修改之后的页面配置

csdn赛道可视化

前端vite+vue3——自动化配置路由布局_javascript_06


拖拽拼图

前端vite+vue3——自动化配置路由布局_vue3_07


2023编码可视化

前端vite+vue3——自动化配置路由布局_自动化_08


抽奖页面

前端vite+vue3——自动化配置路由布局_vite_09


inscode代码



⭐总结

自动化配置路由思路分解

  1. router文件的自动读取形成数据驱动
  2. layout布局页面读取路由,渲染子路由
    vue-router使用

首先引入Vue和Vue Router,并通过Vue.use(VueRouter)来告诉Vue使用VueRouter插件。
然后创建一个VueRouter实例,并通过routes属性配置路由规则。

最后,在创建Vue实例时将router实例传入,并在根组件的模板中添加一个router-view组件来渲染路由组件

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!

前端vite+vue3——自动化配置路由布局_vue3_10

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 最后,感谢你的阅读!