2016-05-23 20 views
1

Mit diesem Code wie würde ich den Render gestaffelt machen? Ich möchte, dass jedes Element einzeln wiedergegeben wird und nicht nur auf einmal gerendert wird. Ich habe setTimeout ausprobiert, weiß aber nicht, wie ich es implementieren soll oder ob es überhaupt der richtige Weg ist.React Native gestaffelt Render

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>); 
} 

Update basierend auf der Antwort, aber es funktioniert immer noch nicht. Der Code in der Antwort war zu unterschiedlich, da dies Native React ist.

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>); 
} 

Antwort

1

Basierend auf dem Code, das Problem ist, dass Sie temp zurück, die eigentlich nichts enthält, da renderLater kehrt nichts.

Eine Lösung besteht darin, ein Element mit einem Status zu erstellen und je nach Status ein oder mehrere Elemente zu rendern. Dies ist ähnlich dem Timer-Element auf der reactjs page, wo der Status jede Sekunde aktualisiert wird, ein neues Rendering auslösen. Anstatt den Ticker jede Sekunde zu ändern, können Sie einen Zähler erhöhen und in renderSelected() alle Elemente bis zu diesem Zähler anzeigen. Es gibt keine renderLater, nur eine this.setState() genannte Regel, die regelmäßig ein neues Rendering mit einer anderen Anzahl von Elementen auslöst.

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

können Sie auch alle Elemente stattdessen erstellen separat von Anfang an mit jeweils einem leeren render() Funktion am Anfang und haben sie etwas an, wenn genügend Zeit verstrichen ist. Zu diesem Zweck können Sie weiterhin die Funktion x.setState() für jedes einzelne Element verwenden, um ein neues Rendering auszulösen. Dies vermeidet das Löschen und Neuzeichnen von bereits gezeichneten Elementen bei jedem Tick.


Alte Antwort:

Sie können für verzögerte Sachen eine globale Warteschlange tun.

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 

Mit dieser Warteschlange, wenn Sie später alle 50ms etwas einige Elemente machen möchten, dann können Sie einfach tun:

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

Sie können die Granularität ändern (wenn die Warteschlange gelesen und geprüft) zu etwas noch weniger als alle 10ms für feinere Kontrolle.

Obwohl ich nicht sehe, was ist das Problem mit der setTimeout. Sie könnten nur tun:

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

Vielleicht ist Ihr Problem kam, dass, wenn Sie den Wert einer Variablen verwenden möchten, die in einem Rückruf in einer Schleife erstellt ändert, dann muss sie durch eine andere Funktion eingeschlossen werden (wie ich es tat indem Sie die neue Funktion renderElementLater anlegen, anstatt dort direkt den Funktionscode zu setzen).

+0

Vielen Dank für Ihre Bemühungen, das ist eine sehr gründliche Antwort. Der Code unterscheidet sich zwar sehr von meinem, da dies nativ reagiert. Ich habe meine Frage mit Timeout basierend auf Ihrer Antwort aktualisiert, aber es funktioniert immer noch nicht. – Hasen

+0

@Hasen Ich habe meine Antwort aktualisiert, den ersten Teil davon. – coyotte508

+0

OK, das ist besser, es wurde ein Fehler mit setInterval geworfen, also habe ich es in "this.interval = TimerMixin.setTimeout (() => {this.tick}, 50);" aber es funktioniert immer noch nicht, es rendert nur das erste Zeichen.Obwohl ich aus dem Code ersehen kann, scheint es nur die Tick-Funktion einmal aufzurufen. – Hasen