麻烦前端大佬看看, THREE 项目重写

247 天前
 johnman

麻烦前端大佬看看

原来有一个 THREE.JS 项目是一个 index.html 直接包含了 three.min.js 和一堆 js 文件。 包含 three.min.js 之后,有了一个全局的 THREE 对象 后面那一堆 js 便对 THREE 这个对象增加了一系列的函数与变量,并且互相引用

示例 EVALoader.js
THREE.EVALoader = function(onLoad, url, options){
	// todo something
}

THREE.AAA = function(){
    // todo something
}

THREE.BBB = function(){
    // todo something
}

打算用 node 改写, 我能想到的方法: 就是也导出一个对象 THREE ,然后每个 js 改写 THREE 的地方,直接引用这个对象并增加函数和变量

这样可行吗?

globals.js 文件

import * as THREE from "three";
window.THREE = THREE;
export default THREE;
EVALoader.js 文件

import * as THREE from "globals"

THREE.EVALoader = function(onLoad, url, options){
    // todo something
}

THREE.AAA = function(){
    // todo something
}

THREE.BBB = function(){
    // todo something
}

如果可行,其他文件直接从 globals 引入 THREE 就可以使用 EVALoader 这个函数?

2114 次点击
所在节点    程序员
22 条回复
okakuyang
247 天前
你应该想说用 es6 模块的方式来写吧?不需要 window.three = three 吧
johnman
247 天前
@okakuyang 是。引用再导出就可以了吗?
貌似原来的 THREE.Vector3 等方法就无法使用了?
bhbhxy
247 天前
不建议用 window.xxx 来挂载全局对象,用模块化的方式,哪里需要就哪里导入,共享数据自己实现一个简易的 vuex
okakuyang
247 天前
import { vector3 } from “three”
okakuyang
247 天前
你要看你引入的版本是不是按模块导出的,如果不是,去找模块导出的版本,如果没有需要自己改导出
johnman
247 天前
@okakuyang

我尝试理解一下,如果 THREE.JS 是按照模块导出的。

我在文件 A 对 THREE 模块 import 之后,增加函数 C 和变量 D 。

其他文件 B 再次 import THREE 模块之后,可以执行函数 C 和读取/修改 D ?
kongkx
247 天前
import 不配 打包工具?
tangchi695
247 天前
threejs 本身就打包了 esm 的版本啊
itbeihe
247 天前
多看看官方文档啊,three.js 官方支持 import 导入的。
另外扩展 three 方法看看这个: https://discourse.threejs.org/t/extending-three-objects-in-r121-module-version/20197/4
```
import { Mesh } from 'three';

// extending an existing function 覆盖已存在方法
const originalRaycast = Mesh.prototype.raycast;
Mesh.prototype.raycast = function(...args) {

const result = originalRaycast.apply( this, args );

// custom logic...

return result;

};

// Or you can add an entirely new function like this 新增方法
Mesh.prototype.customFunction = function() {};
```
johnman
247 天前
@itbeihe

还是不太懂

实际上我想对
import * as THREE from 'three' 这个 THREE 添加新方法

而非对
import { Mesh } from 'three'; 中的 Mesh 添加新方法
horizon
247 天前
你为啥要给 THREE 添加新方法
johnman
247 天前
@horizon 因为原项目存在大量此类操作并且文件之间互相引用。希望可以尽量减少改动
itbeihe
247 天前
@johnman 是想这样么?

````
//myThree.js

import * as Three from 'three'

console.log('start',Three);
// Three 不可扩展,只能用新对象承接
const newThree = {...Three}
newThree.test = function(){
console.log('test');
}

export const three = newThree
````

````
// 调用处
import {three} from "./src/myThree.js"

three.test()

````
jspatrick
247 天前
1. `打算用 node 改写`,nodejs 是无浏览器环境的运行时,肯定不能这样改写,因为没有 window 对象,threejs 包内部也包含一些浏览器环境的变量和函数
2. 猜测你是想用 import 写法,既然已经看到 import 了,不妨重新组织下代码,对 EVALoader 这样的东西统一放置到 loaders 文件夹,不要修改 threejs 导出的对象,使用 import 来导入 EVALoader 和上述的 AAA 、BBB
3. 打包工具问题,如果是体量较大,要工程化,那么建议是上个打包工具的,好处是无脑 install threejs 就完了,倘若代码量不高,浏览器也是支持 script type=module 形式导入的,threejs 同样提供了对应格式的 min 包
horizon
247 天前
@johnman #12
那你要看下原来添加的方法里用了啥啊,可以改成依赖注入的方式,把 THREE 当作参数传入到新方法内。
这样可能比较简单?
johnman
247 天前
@kongkx webpack
johnman
247 天前
nsjs
247 天前
#13 13 楼的方法是对的
johnman
247 天前
@jspatrick EVALoader.js 只是其中一个文件示例。原来项目代码有很多 JS 文件,每个 JS 都在 THREE 对象上加了自己的私活,并且 JS 文件之间直接引用其他文件创建的 THREE.xxx 方法。不知道如何快捷处理这种问题
nsjs
247 天前
@johnman 你这个问题和 node 完全没有关系,就是 js 的模块封装问题
就按 13 楼的方法就可以了。three.js 相当于一个 base module ,其它的如 EVALoader 都是 injector module ,你写一个自己的重导出的 module 就行了,如 my_three.js
```js
import base module

// 导入所有注入
import EVALoader module
import A module
import B module
...
import Z module

// 导出
export default xxx
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/970724

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX