V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
johnman
V2EX  ›  程序员

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

  •  
  •   johnman · Sep 4, 2023 · 3090 views
    This topic created in 972 days ago, the information mentioned may be changed or developed.

    麻烦前端大佬看看

    原来有一个 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 这个函数?

    22 replies    2023-09-04 22:38:45 +08:00
    okakuyang
        1
    okakuyang  
       Sep 4, 2023 via iPhone
    你应该想说用 es6 模块的方式来写吧?不需要 window.three = three 吧
    johnman
        2
    johnman  
    OP
       Sep 4, 2023
    @okakuyang 是。引用再导出就可以了吗?
    貌似原来的 THREE.Vector3 等方法就无法使用了?
    bhbhxy
        3
    bhbhxy  
       Sep 4, 2023
    不建议用 window.xxx 来挂载全局对象,用模块化的方式,哪里需要就哪里导入,共享数据自己实现一个简易的 vuex
    okakuyang
        4
    okakuyang  
       Sep 4, 2023 via iPhone
    import { vector3 } from “three”
    okakuyang
        5
    okakuyang  
       Sep 4, 2023 via iPhone
    你要看你引入的版本是不是按模块导出的,如果不是,去找模块导出的版本,如果没有需要自己改导出
    johnman
        6
    johnman  
    OP
       Sep 4, 2023
    @okakuyang

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

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

    其他文件 B 再次 import THREE 模块之后,可以执行函数 C 和读取/修改 D ?
    kongkx
        7
    kongkx  
       Sep 4, 2023 via iPhone
    import 不配 打包工具?
    tangchi695
        8
    tangchi695  
       Sep 4, 2023
    threejs 本身就打包了 esm 的版本啊
    itbeihe
        9
    itbeihe  
       Sep 4, 2023
    多看看官方文档啊,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
        10
    johnman  
    OP
       Sep 4, 2023
    @itbeihe

    还是不太懂

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

    而非对
    import { Mesh } from 'three'; 中的 Mesh 添加新方法
    horizon
        11
    horizon  
       Sep 4, 2023
    你为啥要给 THREE 添加新方法
    johnman
        12
    johnman  
    OP
       Sep 4, 2023
    @horizon 因为原项目存在大量此类操作并且文件之间互相引用。希望可以尽量减少改动
    itbeihe
        13
    itbeihe  
       Sep 4, 2023
    @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
        14
    jspatrick  
       Sep 4, 2023
    1. `打算用 node 改写`,nodejs 是无浏览器环境的运行时,肯定不能这样改写,因为没有 window 对象,threejs 包内部也包含一些浏览器环境的变量和函数
    2. 猜测你是想用 import 写法,既然已经看到 import 了,不妨重新组织下代码,对 EVALoader 这样的东西统一放置到 loaders 文件夹,不要修改 threejs 导出的对象,使用 import 来导入 EVALoader 和上述的 AAA 、BBB
    3. 打包工具问题,如果是体量较大,要工程化,那么建议是上个打包工具的,好处是无脑 install threejs 就完了,倘若代码量不高,浏览器也是支持 script type=module 形式导入的,threejs 同样提供了对应格式的 min 包
    horizon
        15
    horizon  
       Sep 4, 2023
    @johnman #12
    那你要看下原来添加的方法里用了啥啊,可以改成依赖注入的方式,把 THREE 当作参数传入到新方法内。
    这样可能比较简单?
    johnman
        16
    johnman  
    OP
       Sep 4, 2023
    @kongkx webpack
    nsjs
        18
    nsjs  
       Sep 4, 2023
    #13 13 楼的方法是对的
    johnman
        19
    johnman  
    OP
       Sep 4, 2023
    @jspatrick EVALoader.js 只是其中一个文件示例。原来项目代码有很多 JS 文件,每个 JS 都在 THREE 对象上加了自己的私活,并且 JS 文件之间直接引用其他文件创建的 THREE.xxx 方法。不知道如何快捷处理这种问题
    nsjs
        20
    nsjs  
       Sep 4, 2023
    @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
    ```
    kongkx
        21
    kongkx  
       Sep 4, 2023 via iPhone
    @johnman #17 建议多看看 three.js 的文档,以及示例。 估计有不少是 官方 addon
    johnman
        22
    johnman  
    OP
       Sep 4, 2023
    @nsjs
    用了最土的办法

    globals.js
    import * as MYTHREE from "three";

    global.THREE = MYTHREE;
    global.EVA= EVA;

    console.log("start THREE", global.THREE);
    console.log("start THREE", global.EVA);

    export default MYTHREE;

    在 main.js 里面 import 了
    globals/EVALoader/EVAOptions/EVAPreviews....等等一大堆相互注入依赖的 js ,就搞定了。

    然后在全局暴露了 THREE 和 EVA
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2506 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 06:44 · PVG 14:44 · LAX 23:44 · JFK 02:44
    ♥ Do have faith in what you're doing.