我做了一个简单的应用程序(在react js中)有两个列表,你可以添加元素到该列表.一个是输入元素列表,另一个是跨度列表.
添加新元素后,span列表完美呈现,但输入列表呈现的方式不同.
这就是我的反应类的样子
var App = React.createClass({ getInitialState: function(){ return { 'app': { 'data': this.props.data,'data2': this.props.data2 } }; },onclick: function(){ var dat = this.state.app.data; var val = this.refs.input.getDOMNode().value; dat.splice(0,val); var dat2 = this.state.app.data2; dat2.splice(0,val); this.setState({'app': { 'data': dat,'data2': dat2 }}); },renderElement: function(i){ return( <input defaultValue={i} /> ); },renderElement2: function(i){ return( <span>{i}</span> ); },render: function(){ var self = this; return( <div> <input type="text" ref="input" placeholder="Enter a value"/> <input type="button" value="Add value" onClick={this.onclick} /> <div className="col2"> {this.state.app.data.map(function(page,i){ return( <div key={i}>{self.renderElement(page)}</div> ); })} </div> <div className="col2"> {this.state.app.data2.map(function(page,i){ return( <div key={i}>{self.renderElement2(page)}</div> ); })} </div> </div> ); } });
这就是应用程序的呈现方式
var data = [1,2,3]; var data2 = [1,3]; React.render(<App data={data} data2={data2}/>,document.getElementById("main"));
这是DEMO
My test case: I add 55 and expect the results to look like this 55 1 2 3 55 1 2 3 But I get 1 2 3 3 55 1 2 3
我错过了一些基本的东西吗?
首先渲染(粗略地)看起来像这样:
<div> <div key={0}><input defaultValue="1" /></div> <div key={1}><input defaultValue="2" /></div> <div key={2}><input defaultValue="3" /></div> </div> <div> <div key={0}><span>1</span></div> <div key={1}><span>2</span></div> <div key={2}><span>3</span></div> </div>
很酷,没问题.然后假设我在框中输入’foo’并单击Add Value.状态更新通过在第一个项目之前插入(侧注:splice(0,x)是unshift(x)),然后渲染:
<div> <div key={0}><input defaultValue="foo" /></div> <div key={1}><input defaultValue="1" /></div> <div key={2}><input defaultValue="2" /></div> <div key={3}><input defaultValue="3" /></div> </div> <div> <div key={0}><span>foo</span></div> <div key={1}><span>1</span></div> <div key={2}><span>2</span></div> <div key={3}><span>3</span></div> </div>
现在是时候React采取这两个,并找出改变了什么.为此,它会比较组件(div,span或此处的输入)和键.
从span部分开始,它看到所有标签都是相同的,但是它有一个它在最后没有见过的新密钥.它还看到div [0] span,div [1] span和div [2] span的值都发生了变化.它在末尾插入带有文本3的新元素,并更新其他跨度.效率不高,但确实有效.
现在输入……它的作用大致相同.前三个输入的键和标签是相同的,它告诉每个输入他们正在更新,他们检查他们是否有价值道具,如果没有,请拒绝做任何事情.
它看到最后有一个新的输入.它位于div [3]输入端,其defaultValue为“3”. React插入新输入,将值设置为3,更新完成.
继续,上面的过程是相同的,它继续更新跨度,并每次插入一个新的div span和div输入.
这里的主要问题是,除了我认为不应该使用的defaultValue之外,关键是颠倒了!项目在开头插入,因此键应该下降,而不是上升.这可以通过使用项目的长度并从中减去索引来解决.如果长度为4,则键为4,3,1.
this.state.app.data.map(function(page,i,items){ return( <div key={items.length - i}>{self.renderElement(page)}</div> ); })
React然后说’哦,开头有一个新项目,我应该在那里插入一个节点’,每个人都很高兴.结束.