如何在Reactjs中创建组件实例

How to make component instances in Reactjs

本文关键字:创建组 组件 实例 创建 Reactjs      更新时间:2023-09-26

当我在init()中调用ReactDom.render时,仅创建一个g标记,并且所有圆都在该g标记内创建。但我希望在每个ReactDom.render调用上都必须创建一个单独的g标记。我对React中组件的了解是,我们可以使用React.createClass实例化任意数量的组件。我该怎么做?

var Rect = React.createClass({
  render: function() {
    return (
      React.createElement('circle', {
        cx: this.props.cx,
        cy: this.props.cy,
        r: this.props.r,
        fill: '#00ff00'
      });
    );
  }
});
var globalArray = [];
var someFunc = function(cx, cy, r) {
  var Factory = React.createClass({
    render: function() {
      var localArray = [];
      for(var i = 0; i < 1; i++) {
        localArray[i] = React.createElement(Rect, {
          key: globalArray.length,
          cx: cx,
          cy: cy,
          r: r
        })
      }
      globalArray[globalArray.length] = localArray[0];
      return (
        React.createElement('g', {}, globalArray)
      )
    }
  });
  return Factory;
}
var randomNumber = function (x,y) {
  return ~~(Math.floor(((Math.random()*x) + y )));
}
var obj = {
  init: function() {
    var element;
    for(var i = 0; i < 100; i++) {
      var cx = randomNumber(1200,40);
      var cy = randomNumber(600,40);
      var r = randomNumber(30,20);
      element = someFunc(cx,cy,r);
      ReactDOM.render(
        React.createElement(element,{}),         
        document.getElementById('svg')
      );
    }       
  }
}

您可能会发现,让代码的结构由React组件定义,而不是由您自己的函数和全局变量定义,会让您受益匪浅。

一般来说,如果你发现自己多次呼叫ReactDOM.render,那么可能出了问题。

顶级组件

与其将100个组件渲染为一个元素,不如定义一个由100个子组件实例组成的顶级组件,然后渲染一次。

var Graphics = React.createClass({
  // ...
});
ReactDOM.render(
  React.createElement(Graphics, null),
  document.getElementById('svg')
);

我们将创建一个Graphics组件,可以将其用作其余组件的父组件我们只需要渲染一次

与其将圆列表存储在全局数组中,不如在新的顶级组件上使用state属性。这样,无论何时更新,组件都将重新渲染以反映更改。

getInitialState: function() {
  // by default there are no circles (empty array)
  return { circles: [] };
},
componentWillMount: function() {
  var circles = [];
  for(var i = 0; i < 100; i++) {
    // rather than storing actual circles, we just store
    // the props that are needed to create them
    circles.push({
      cx: randomNumber(1200, 40),
      cy: randomNumber(600, 40),
      r: randomNumber(30,20)
    });
  }
  this.setState({ circles: circles });
}

getInitialState允许我们为this.state上的属性定义默认值,componentWillMount允许在DOM中呈现组件之前运行代码。

渲染

既然Graphics组件已经了解了圆列表,我们就必须描述它的渲染方式。

render: function() {
  var circles = this.state.circles.map(function(props) {
    return React.createElement(Circle, props);
  });
  return React.createElement('g', null, circles);
}

此函数使用map使用我们存储在this.state.circles中的道具创建Circle组件。

结论

React在您将组件构建为生活在一个顶级容器组件中时最有效,就像我们在这里创建的那样。与其做任何命令性操作(比如每次循环和渲染组件),不如寻找声明性的替代方案。

React希望您告诉它您想要什么,而不是应该如何

在这种情况下,你想要的是一个内部有许多随机大小和位置的圆圈的组件,但你试图做的是向React解释应该如何实现这一点。

var Circle = React.createClass({
  render: function() {
    // ...
  }
});
var Graphics = React.createClass({
  getInitialState: function() {
    // ...
  },
  componentWillMount: function() {
    // ...
  },
  render: function() {
    // ...
  }
});

生成的代码不仅应该更短、更易于遵循,而且还应该易于重构。不需要做太多工作,就可以将配置细节(如圆圈的数量)移动为Graphics的道具。