
本文详解如何在 vue 3(javascript 版本)项目中正确集成 three.js 基础场景,涵盖 dom 挂载、生命周期协调、渲染循环管理及常见陷阱规避。
本文详解如何在 vue 3(javascript 版本)项目中正确集成 three.js 基础场景,涵盖 dom 挂载、生命周期协调、渲染循环管理及常见陷阱规避。
在 Vue 3 的响应式架构下直接嵌入 Three.js 渲染逻辑,需特别注意 DOM 元素可用性、渲染器生命周期与 Vue 组件生命周期的协同。原生 Three.js 示例依赖 document.body.appendChild(),但在 Vue 单文件组件(SFC)中,必须通过 ref 获取真实 DOM 节点,并在 onMounted 钩子中安全挂载渲染器——这是避免 Cannot read property 'appendChild' of null 等错误的关键。
以下是一个可直接运行的 App.vue 完整实现(使用 JavaScript,非 TypeScript):
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as THREE from 'three';
// 创建 DOM 引用容器
const target = ref();
// 初始化 Three.js 核心对象
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(500, 500); // 推荐显式设置尺寸,避免默认拉伸
renderer.setPixelRatio(window.devicePixelRatio); // 提升高 DPI 屏幕显示质量
// 创建绿色立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
// 动画循环函数(闭包内维持引用,避免重复创建)
let animationId = null;
function animate() {
animationId = requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
// 组件挂载后:挂载渲染器 DOM 并启动动画
onMounted(() => {
if (target.value) {
target.value.appendChild(renderer.domElement);
animate();
}
});
// 【重要】组件卸载前清理资源,防止内存泄漏
onUnmounted(() => {
if (animationId) {
cancelAnimationFrame(animationId);
}
if (renderer.domElement && renderer.domElement.parentNode) {
renderer.domElement.parentNode.removeChild(renderer.domElement);
}
renderer.dispose(); // 释放 WebGL 资源
});
</script>
<template>
<div ref="target" class="three-container"></div>
</template>
<style scoped>
.three-container {
width: 500px;
height: 500px;
margin: 2rem auto;
border: 1px solid #eee;
}
</style>✅ 关键要点说明:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- ref + onMounted 是黄金组合:确保 renderer.domElement 只在真实 DOM 节点就绪后才插入;
- 显式 setSize() 优于 renderer.setSize(window.innerWidth, ...):避免因响应式容器尺寸变化导致渲染异常,推荐结合 CSS 控制容器宽高,Three.js 渲染器按需适配;
- 务必调用 renderer.dispose() 和 cancelAnimationFrame:Vue 组件可能被复用或销毁,未清理的动画帧和 WebGL 上下文将引发内存泄漏;
- 添加 antialias: true 和 setPixelRatio:显著提升视觉质量,尤其在 Retina 屏幕上;
- 避免在 setup() 顶层执行渲染逻辑:Three.js 对象(如 scene, camera)可定义在顶层,但 DOM 操作与动画启动必须延迟至 onMounted。
? 进阶提示:如需响应窗口缩放,可监听 window.resize 事件并更新 camera.aspect 与 renderer.setSize(),但需注意防抖以避免高频重绘。
立即学习“前端免费学习笔记(深入)”;
遵循以上模式,你即可稳健地将 Three.js 场景集成进任意 Vue 3 页面组件中,为构建 3D 可视化、产品预览或交互式教学内容奠定坚实基础。

















