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

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

⭐前言

大家好,我是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

选择typescript

💖 添加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");

⭐实现效果

基础路由页面

添加一个图片页面路由

⭐总结

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

  1. 高性能:Vite采用了异步快速共识算法。具体来说,Vite使用了一种名为HDPoS的共识机制,该机制能够实现每秒高达10,000笔交易的吞吐量。这使得Vite成为一个高效、快速的公链平台。
  2. 无 gas 模型:Vite引入了自身独有的无 gas 模型,用户无需支付燃气费用即可进行交易和执行智能合约。这大大降低了用户使用区块链应用的成本。
  3. 轻量级智能合约:Vite采用了基于图灵完备语言的Solidity智能合约,这使得Vite的智能合约编写和部署变得简单和高效。
  4. 高度可扩展:Vite通过使用DAG(有向无环图)机制,实现了高度可扩展性。DAG的使用可以有效地提高网络吞吐量,并克服了其他公链平台中存在的交易堵塞问题。
  5. 自我优化:Vite的共识算法允许网络参与者在节点之间进行随机选举,并进行高效的数据通信。这种机制能够自动优化网络性能,确保链上交易的快速确认。

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

⭐结束

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


目录
相关文章
|
13天前
|
JavaScript 前端开发 开发者
Vue 3中的Proxy
【10月更文挑战第23天】Vue 3中的`Proxy`为响应式系统带来了更强大、更灵活的功能,解决了Vue 2中响应式系统的一些局限性,同时在性能方面也有一定的提升,为开发者提供了更好的开发体验和性能保障。
30 7
|
14天前
|
前端开发 数据库
芋道框架审批流如何实现(Cloud+Vue3)
芋道框架审批流如何实现(Cloud+Vue3)
36 3
|
13天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
33 1
|
13天前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
34 1
|
3天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
3天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
3天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
3天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
2天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
4天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。