React Native交错渲染

时间:2016-05-23 12:34:35

标签: javascript ios reactjs react-native

使用此代码,如何使渲染交错?我希望它逐个渲染每个元素而不是一次渲染所有元素。我已经尝试过setTimeout但不知道如何实现它,或者它是否正确的方法来实现它。

renderSelected() {
  var temp=[];
  for (var i = 0; i < 11; i++) {
    temp.push(this.selected(i))
  }
  return temp;
 }

selected(number) {
  return (<View key={number} style={styles.normal}  >
    <Text>{number}</Text>
  </View>);
}

根据答案进行更新,但仍然无效。答案中的代码太不同了,因为这是React Native。

  renderLater(i) {
   TimerMixin.setTimeout(() => {
   this.selected(i);
   }, 100);
 }

renderSelected() {
  var temp=[];
  for (var i = 0; i < 11; i++) {
    temp.push(this.renderLater(i))
  }
  return temp;
 }

selected(number) {
  return (<View key={number} style={styles.normal}  >
    <Text>{number}</Text>
  </View>);
}

1 个答案:

答案 0 :(得分:1)

根据代码,问题是您返回实际上什么都不包含的temp,因为renderLater什么都不返回。

解决方案是创建一个具有状态的元素,并根据状态渲染一个或多个元素。这类似于reactjs page上的计时器元素,其中状态每秒更新一次,触发新的渲染。您可以增加一个计数器,而不是在每秒更改自动收报机,并在renderSelected()显示该计数器的所有元素。没有renderLater,只有this.setState()被称为定期触发具有不同数量元素的新渲染。

var MyClass = React.createClass({
  getInitialState: function() {
    return {counter: 0};
  },
  tick: function() {
    if (this.state.counter >= 10) return;
    this.setState({counter: this.state.counter + 1});
  },
  componentDidMount: function() {
    this.interval = setInterval(() => {this.tick();}, 50);
  },
  componentWillUnmount: function() {
    clearInterval(this.interval);
  },
  render: function() {
      var temp=[];
      for (var i = 0; i <= 10 && i <= this.state.counter; i++) {
          temp.push(this.selected(i))
      }
      return temp;
  },
  selected: function(number) {
      return (<View key={number} style={styles.normal}  >
         <Text>{number}</Text>
      </View>);
  }
});

ReactDOM.render(<MyClass />, mountNode);

Live demo

您也可以在开头分别创建所有元素,每个元素在开头都有一个空的render()函数,并在足够的时间过去时显示它们。为此,您仍然可以为每个单独的元素使用x.setState()函数来触发新的渲染。这样可以避免在每个刻度处擦除和重绘已绘制的元素。

旧回答:

你可以为延迟的东西做一个全局队列。

var queue = [];

/* executes all element that have their delay elapsed */
function readQueue() {
    var now  = (new Date()).getTime();
    for (var i = 0; i < queue.length; i++) {
        if (queue[i][0] <= now) { 
            queue[i][1]();
        } else {
            if(i != 0) queue = queue.slice(i);
            return;
        }
    }
    queue = [];
}

/* Delay is in milliseconds, callback is the function to render the element */
function addQueue(delay, callback) {
    var absoluteTime = (new Date()).getTime() + delay;
    for (var i = 0; i < queue.length; i++) {
        if (absoluteTime < queue[i][0]) {
             queue.splice(i, 0, [absoluteTime, callback]);
             return;
        }
    }
    queue.push_back([absoluteTime, callback]);
}

var queueTimer = setInterval(readQueue, 10); //0.01s granularity

使用该队列,如果你想在每50ms之后渲染一些元素,那么你可以这样做:

function renderElementLater(time, index) {
    /* render */
    addQueue(time, function(){ReactDOM.render(selected(index), mountNode);}):
}
for (var i = 0; i <= 10; i++) {
    renderElementLater(50*i, i);
}

您可以将粒度(在读取和检查队列时)更改为甚至小于每10毫秒的粒度,以便更好地控制。

虽然,我看不出setTimeout的问题。你可以这么做:

function renderElementLater(time, index) {
    /* render */
    setTimeout(function(){ReactDOM.render(selected(index), mountNode);}, time):
}
for (var i = 0; i <= 10; i++) {
    renderElementLater(50*i, i);
}

也许你的问题是,如果你想使用在循环中创建的回调中变化的变量的值,那么它需要被另一个函数包围(就像我通过创建新函数{{1}所做的那样)而不是直接在那里放置功能代码)。