代码之家  ›  专栏  ›  技术社区  ›  Chris

React/NPM:如何封装组件?

  •  1
  • Chris  · 技术社区  · 4 年前

    假设我有下面的react应用程序,它显示一个旋转立方体。

    npm create-react-app
    
    vi src/App.js
    

    复制粘贴以下内容:

    import React, { Component } from "react";
    import ReactDOM from "react-dom";
    import * as THREE from "three";
    class App extends Component {
      componentDidMount() {
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );
        // document.body.appendChild( renderer.domElement );
        // use ref as a mount point of the Three.js scene instead of the document.body
        this.mount.appendChild( renderer.domElement );
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        var cube = new THREE.Mesh( geometry, material );
        scene.add( cube );
        camera.position.z = 5;
        var animate = function () {
          requestAnimationFrame( animate );
          cube.rotation.x += 0.01;
          cube.rotation.y += 0.01;
          renderer.render( scene, camera );
        };
        animate();
      }
      render() {
        return (
          <div ref={ref => (this.mount = ref)} />
        )
      }
    }
    export default App
    
    npm run build
    

    瞧,旋转立方体!


    但是 下一个 我尝试做的事情是:封装旋转的立方体并创建一些下拉列表,允许我查看立方体或其他东西。

    不过,我没有得到一个下拉列表,因为我无法将多维数据集类封装在函数下面:

    mport React, { Component } from "react";
    import ReactDOM from "react-dom";
    import * as THREE from "three";
    class ICube extends Component {
      componentDidMount() {
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );
        // document.body.appendChild( renderer.domElement );
        // use ref as a mount point of the Three.js scene instead of the document.body
        this.mount.appendChild( renderer.domElement );
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        var cube = new THREE.Mesh( geometry, material );
        scene.add( cube );
        camera.position.z = 5;
        var animate = function () {
          requestAnimationFrame( animate );
          cube.rotation.x += 0.01;
          cube.rotation.y += 0.01;
          renderer.render( scene, camera );
        };
        animate();
      }
      render() {
        return (
          <div ref={ref => (this.mount = ref)} />
        )
      }
    }
    export default function App() {
      var cube = ICube()
      return ( 
          <div ref={ref => (cube.mount = ref)} />
      )   
    }
    

    这会生成,但不会渲染。我不确定这个封装应该如何进行。有什么特别的方法来封装它吗?

    我还尝试创建:

    export default class App extends Component {
      cube = ICube()
      componentDidMount() {
      }
      render() {
        return (
          <div ref={ref => (this.cube.mount = ref)} />
        )
      }
    }
    

    作为一个直接的封装,但这不起作用。

    2 回复  |  直到 4 年前
        1
  •  1
  •   98sean98    4 年前

    如果你只是想 ICube 在另一个组件中渲染。简单地做

    // class component
    export default class App extends Component {
      render() {
        return (
          <div>
            <ICube />
            {/* more components */}
          </div>
        )
      }
    }
    
    // functional components
    export default function App() {
      return (
        <div>
          <ICube />
          {/* more components */}
        </div>
      );
    }
    

    cube = ICube() 当使用类组件时。看到了吗 React docs . 组合可以使用类组件和函数组件的任何方式来完成。

        2
  •  0
  •   Damodar Hegde    4 年前

    您不需要为此创建引用。只需导入组件并在渲染函数中使用它

    import React, { Component } from "react";
    import ReactDOM from "react-dom";
    import * as THREE from "three";
    class ICube extends Component {
      componentDidMount() {
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );
        // document.body.appendChild( renderer.domElement );
        // use ref as a mount point of the Three.js scene instead of the document.body
        this.mount.appendChild( renderer.domElement );
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
        var cube = new THREE.Mesh( geometry, material );
        scene.add( cube );
        camera.position.z = 5;
        var animate = function () {
          requestAnimationFrame( animate );
          cube.rotation.x += 0.01;
          cube.rotation.y += 0.01;
          renderer.render( scene, camera );
        };
        animate();
      }
      render() {
        return (
          <div className"some-style-class">
             <App />
             {//some other components}
          </div>
        )
      }
    }
    
    

    若要有条件地渲染形状,可以将道具传递给应用程序组件,如下所示

    <App
      shape={this.state.shape} 
    />
    

    形状类型的值可以来自您创建的下拉组件