vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)

发布时间:2024年01月14日


yma16-logo

?前言

大家好,我是yma16,vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)。
背景
搭建一个模型可视化平台,可以对3d模型进行旋转、缩放、拖拽的基础操作,

💖vue3系列相关文章

vue3 + fastapi 实现选择目录所有文件自定义上传到服务器
前端vue2、vue3去掉url路由“ # ”号——nginx配置
csdn新星计划vue3+ts+antd赛道——利用inscode搭建vue3(ts)+antd前端模板
认识vite_vue3 初始化项目到打包
python_selenuim获取csdn新星赛道选手所在城市用echarts地图显示
让大模型分析csdn文章质量 —— 提取csdn博客评论在文心一言分析评论区内容
前端vue3——html2canvas给网站截图生成宣传海报
vue3+echarts应用——深度遍历html的dom结构并用树图进行可视化
vue3新特性
Vue 3 是 Vue.js 的最新版本,它引入了许多新的特性和改进。以下是一些 Vue 3 的新特性:

  1. Composition API:Vue 3 引入了一个新的 API,称为 Composition API。Composition API 允许开发者以逻辑组织代码,而不是按照组件的选项进行组织。这使得代码更易于维护和重用。

  2. 更快的渲染速度:Vue 3 对渲染引擎进行了改进,使得渲染速度更快。它采用了一个新的虚拟 DOM 比较算法,该算法在进行 Diff 计算时更加高效。

  3. 更小的包体积:Vue 3 的包体积比 Vue 2 更小,这意味着它可以更快地加载和运行。

  4. 改进的 TypeScript 支持:Vue 3 对 TypeScript 的支持得到了改进。它提供了更好的类型推断和编辑器支持,使开发过程更加流畅和安全。

  5. 新的响应性系统:Vue 3 引入了一个新的响应性系统,使得在组件中跟踪和更新状态更加简单和高效。

  6. 新的生命周期钩子:Vue 3 引入了一些新的生命周期钩子函数,使开发者可以更好地控制组件的生命周期。

  7. 更好的 TypeScript 支持:Vue 3 更好地支持 TypeScript,提供了更好的类型推断和类型检查。

这些都是 Vue 3 的一些主要特性,它们使开发者可以更好地开发和维护 Vue.js 应用程序。

?搭建vue3项目过程

在windows环境使用node版本>16

💖 初始化项目

npm创建项目

$ npm create vite@latest vue_threejs_front --template vue

选择vue
vue-create
选择typescript
ts-lang

💖 添加antd和router依赖

在package.json添加 vue-router和ant-design-vue

  "dependencies": {
    "ant-design-vue": "^3.2.15",
    "eslint-config-standard-with-typescript": "^24.0.0",
    "eslint-plugin-import": "^2.26.0",
    "less": "^4.1.3",
    "unplugin-vue-components": "^0.22.12",
    "vue": "^3.2.45",
    "vue-router": "^4.1.6",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@types/node": "^18.11.18",
    "@vitejs/plugin-vue": "^4.0.0",
    "typescript": "^4.9.3",
    "vite": "^4.0.0",
    "vue-tsc": "^1.0.11"
  }

💖 vite配置项映射目录和代理

vite配置项

  1. 映射目录src -> @
  2. 初始化加载main.less样式文件
  3. api本地代理
import { defineConfig,loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
// @ts-ignore
import { resolve } from "path";
// @ts-ignore
import Components from "unplugin-vue-components/vite";
// @ts-ignore
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";

// https://vitejs.dev/config/
export default defineConfig(({mode})=>{
  // 运行模式
  console.log('mode',mode)
  // 当前路径
  console.log('process.cwd()',process.cwd())
  // @ts-ignore
  const env=loadEnv(mode,process.cwd())
  console.log('env',env)
  const proxy={
    "^/api/": {
      target: env.VITE_APP_HOST,
      changeOrigin: true,
      ws: true,
      rewrite: (path) => path.replace(/^\/api/, ""),
    },
  };

  return {
    // 打包相对路径
    base: './',
    server: {
      port: 3000,
      open: true,
      cors: true,
      proxy: {
        ...proxy
      },
    },
    "css": {
      preprocessorOptions: {
        less: {
          javascriptEnabled: true,
          patterns: [resolve(__dirname, "./src/style/main.less")],
        },
      },
    },
    resolve: {
      alias: {
        "@": resolve(__dirname, "src"),
      },
    },
    plugins: [
      vue(),
      Components({
        resolvers: [AntDesignVueResolver()],
      }),
    ],
  }
});

💖 antd国际化

App.vue配置国际化

<script setup lang="ts">
  import { ref } from "vue";
  import zhCN from "ant-design-vue/es/locale/zh_CN";
  import dayjs from "dayjs";
  import "dayjs/locale/zh-cn";
  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;
  }
</style>

💖 layout布局封装

layout读取routes展示路由
layout/index.vue

<script setup lang="ts">
    import {
        UserOutlined,
        FundOutlined,
        MenuUnfoldOutlined,
        MenuFoldOutlined,
        PoweroffOutlined,
    } from "@ant-design/icons-vue";
    // @ts-ignore
    import { reactive, computed,h,onMounted} from "vue";
    import { useRouter } from "vue-router";

    //router
    const router = useRouter();
    interface stateType {
        selectedKeys: Array<String>;
        openKeys:Array<String>;
        collapsed: Boolean;
        title: string;
        menuList:any;
    }
    const state: stateType = reactive({
        title: "vue3平台",
        openKeys:[],
        selectedKeys: [],
        collapsed: false,
        menuList:[ ]
    });
    interface contentType {
        url: string;
        title: string;
        kind:string;
    }

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

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

    const renderIcon=(icon)=>{
        // return h(icon)
        return ''
    }
    onMounted(() => {
        console.log('router.current.value',router)

        const {routes}=router.options
        state.menuList=routes.map(item=>{
            console.log('item')
            return {
                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,
                     }
                })
            }
        })
    });
</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.id" @click="clickMenu(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
                    :style="{
          margin: '24px 16px',
          padding: '24px',
          background: '#fff',
          minHeight: '280px',
        }"
            >
<!--                    渲染子路由-->
                    <router-view/>
            </a-layout-content>
        </a-layout>
    </a-layout>
</template>

<style lang="less">
    .layout-container {
        width: 100%;
        height: 100%;
    }
    #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>

💖 vite读取modules目录文件作为路由

router.ts

// import { useStore } from "vuex";
import * as VueRouter from "vue-router";


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

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

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

💖 main入口配置文件

main.ts

// @ts-ignore
import { createApp } from "vue";
// @ts-ignore
import App from "./App.vue";
// @ts-ignore
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";
// @ts-ignore
import Router from "./router/index.ts";
const app = createApp(App);
app.use(Antd);
// router
app.use(Router);
app.mount("#app");

?实现效果

基础路由页面
base-router
添加一个图片页面路由
img-router

?总结

Vite是一个高性能的公链平台,具有以下优势:

  1. 高性能:Vite采用了异步快速共识算法。具体来说,Vite使用了一种名为HDPoS的共识机制,该机制能够实现每秒高达10,000笔交易的吞吐量。这使得Vite成为一个高效、快速的公链平台。

  2. 无 gas 模型:Vite引入了自身独有的无 gas 模型,用户无需支付燃气费用即可进行交易和执行智能合约。这大大降低了用户使用区块链应用的成本。

  3. 轻量级智能合约:Vite采用了基于图灵完备语言的Solidity智能合约,这使得Vite的智能合约编写和部署变得简单和高效。

  4. 高度可扩展:Vite通过使用DAG(有向无环图)机制,实现了高度可扩展性。DAG的使用可以有效地提高网络吞吐量,并克服了其他公链平台中存在的交易堵塞问题。

  5. 自我优化:Vite的共识算法允许网络参与者在节点之间进行随机选举,并进行高效的数据通信。这种机制能够自动优化网络性能,确保链上交易的快速确认。

综上所述,Vite具有高性能、无 gas 模型、轻量级智能合约、高度可扩展和自我优化等优势,使其成为一个值得关注的公链平台。

?结束

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

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

文章来源:https://blog.csdn.net/qq_38870145/article/details/135579800
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。