2014-12-13 44 views
2

我想创建一个随机随机播放一些动画的列表。反应:在列表混洗的连续呈现中会发生什么?

这里是the fiddle对于它我用key道具来识别每个孩子。

http://jsfiddle.net/1wcpLLg4/

var ListAnimate = React.createClass({ 
    list: [ 
     {id: 1, caption: "Hello"}, 
     {id: 2, caption: "There"}, 
     {id: 3, caption: "Whatsup"}, 
     {id: 4, caption: "Sanket"}, 
     {id: 5, caption: "Sahu"}, 
    ], 
    shuffle: function() { 
     this.list.shuffle(); // Shuffles array! 
     this.forceUpdate(); 
    }, 
    render: function() { 
     return <div> 
      <button onClick={this.shuffle}>Shuffle</button> 
      <ul> 
       {this.list.map(function(el, i){ 
        return <li key={el.id} style={ {top: (i*60)+'px'} }>{el.caption} {el.id}</li>; 
       })} 
      </ul> 
     </div>; 
    } 
}); 

React.render(<ListAnimate />, document.body); 

React docs about Dynamic Children,它指出key支柱,以便在连续呈现,以确定在数组中的元素使用。因此,刚刚重新排序的项目不能卸载并安装到新的位置,而应该重新定位,但似乎并不在小提琴中发生,其中列表顶部的节点总是未安装并安装在不同的位置。

但是对于底部的元素似乎与动画效果很好。

+0

当您完成更改时,您需要点击小提琴中的小提琴。链接只是去你好世界小提琴。此外,您需要在问题中包含小提琴中的代码,以防jsfiddle消失。 – FakeRainBrigand 2014-12-13 08:59:57

+0

对不起,现在更新! (y) – 2014-12-13 09:11:07

回答

2

我创建了一个小提琴,以显示li元素实际上未安装/卸载。

http://jsfiddle.net/jq9p7hnd/

我已经转换li元件MyLi元件和记录的消息时componentDidMountcomponentWillUnmount函数被调用。只有componentDidMount回调期间称为第一渲染和他们都不洗牌后,被称为:

var MyLi = React.createClass({ 


    componentDidMount : function(){ 
     console.log("MyLi component did mount."); 
    }, 

    componentWillUnmount : function(){ 
     console.log("MyLi component will unmount."); 
    }, 

    render : function(){ 

     return <li {...this.props}>{this.props.children}</li> 

    } 
}); 

var ListAnimate = React.createClass({ 
    list: [ 
     {id: 1, caption: "Hello"}, 
     {id: 2, caption: "There"}, 
     {id: 3, caption: "Whatsup"}, 
     {id: 4, caption: "Sanket"}, 
     {id: 5, caption: "Sahu"}, 
    ], 
    shuffle: function() { 
     this.list.shuffle(); 
     this.forceUpdate(); 
    }, 
    render: function() { 
     return <div> 
      <button onClick={this.shuffle}>Shuffle</button> 
      <ul> 
       {this.list.map(function(el, i){ 
        return <MyLi key={el.id} style={ {top: (i*60)+'px'} }>{el.caption} {el.id}</MyLi>; 
       })} 
      </ul> 
     </div>; 
    } 
}); 
window.React = React; 
React.render(<ListAnimate />, document.body); 









Array.prototype.shuffle = function() { 
    var i = this.length, j, temp; 
    if (i == 0) return this; 
    while (--i) { 
    j = Math.floor(Math.random() * (i + 1)); 
    temp = this[i]; 
    this[i] = this[j]; 
    this[j] = temp; 
    } 
    return this; 
} 
+0

良好的调试,但定位有什么错误?这不是一个CSS问题,我检查了Inspector Elements面板。 – 2014-12-13 09:27:46

+0

我认为React对实际的DOM元素进行重新排序(它不会丢弃现有的DOM元素和React类实例并创建新的元素)并更新它们的'top'样式属性。 – nilgun 2014-12-13 09:32:18

+1

如果它重新命令现有的DOM,那么为什么只有那些从底部到顶部移动的元素是动画而不是从顶部到底部使用元素的?在谷歌浏览器的调试器中,如果元素面板向下移动,则它会丢失选定的元素,但选择仍然保留在上升的元素上。 – 2014-12-13 09:38:23

3

请记住,你正在寻找的那种动画,你需要始终保持DOM在同订单并只更新它们在组件的渲染功能中的位置。

我修改使用这种策略的第一小提琴:http://jsfiddle.net/0maphg47/1/

render: function() { 
    // create a sorted version of the list to render the DOM 
    var sortedCopy = this.state.list.slice().sort(function(a, b) { 
     return a.id - b.id; 
    }); 

    return <div> 
     <button onClick={this.shuffle}>Shuffle</button> 
     <ul> 
      {sortedCopy.map(function(el, i) { 
       // find the position of the element in the shuffled list 
       // which gives the position the element must be 
       var pos = this.state.list.indexOf(el); 
       return <li key={el.id} style={ {top: (pos*60)+'px'} }> 
        {el.caption} {el.id} 
       </li>; 
      }, this)} 
     </ul> 
    </div>; 
} 

仍然有改进的余地,但我会离开,给你。

+0

感谢您的详细解答和小提琴!这工作得很好,但我的解决方案也应该工作。它看起来像React的渲染功能有问题(如其他答案的评论中所述) – 2014-12-14 19:51:52

+2

您是否阅读过关于React算法的这篇文章?在最后一节中,“你可以表达一个事实,即一棵子树已经在其兄弟姐妹之间移动了,但是你不能说它已经移动到别的地方了。” http://facebook.github.io/react/docs/reconciliation.html – Becojo 2014-12-14 20:52:40

+0

谢谢!你帮我解决了一个与复制JS数组有关的单独问题,'.slice()'是我在'this.state.list.slice()中需要的关键部分。sort ...' – 2015-03-19 23:01:29