简单的添加/删除组件模式
Simple Add / Remove Component Pattern
我对 React 中的这种模式感到很困惑。我在其他地方看到过它,但它似乎不正确。
给定以下代码:
/** @jsx React.DOM */
var React = window.React = require('react'),
Item = require("./ui/Item");
var ItemApp = React.createClass({
getInitialState: function() {
return {
items: [ "Example Item" ] // we want one thing to render initially
}; // so prepopulate with one thing
},
getDefaultProps: function () {
return {
index: 1
}
},
onAddItem: function (e) {
var debts = this.state.debts.push( "New Item " + this.props.index);
this.setState({ items: this.state.items });
this.props.index++;
},
onRemoveItem: function (i) {
// splice here
this.state.items.splice(i, 1);
this.setState({ items: this.state.items });
this.props.index--;
},
render: function () {
var items = this.state.items;
var closeFn = this.onRemoveItem;
return (
<div className="col-lg-12">
<div className="cold-md-3"></div>
<div className="col-md-3 col-md-offset-9">
<button type="button" className="btn btn-default" onClick={this.onAddItem}><span className="glyphicon glyphicon-plus"></span> Add New Debt</button>
</div>
{items.map(function (item, i) {
return <Item name={item} closeFn={closeFn.bind(null, i)} key={i} />;
})}
</div>
);
}
});
上面的示例按预期工作(它是一个列表,您可以随意添加和删除内容)但是每当我添加内容时都会重新呈现整个内容。
所以只加了一个组件整个渲染了3次。单击两次后,它将渲染 5 次。您可以看到为什么这可能是个问题。
这看起来效率很低,有更好的方法吗?
如果您想手动管理 dom,React 可能不适合您。如果你真的愿意,你总是可以比抽象做得更好。
在 React 中,通常最好的目标是能够清楚地表达其 React 意图的代码,并让它做它的事情。
您的代码很接近,唯一的问题是您的 key
属性不能唯一地反映数组中的项目。当你有一个堆栈时,基于索引的键是 100% 好的。我给了一个类似的问题。
要在这里真正解决这个问题,因为任何项目都可以随时删除,所以您需要在项目本身中编码一个唯一标识符。您应该存储一个对象数组 [{id: '1', text: "a"}, {id: '2', text: "b"}, {id: '3', text: "c"}]
,而不是存储一个字符串数组 ["a", "b", "c"]
。然后你可以使用这个id作为你的密钥,这样会更有效率。
这与问题无关,但是this.props.index--
是在修改道具,这很糟糕而且不可靠。如果你因为某些原因需要保留一个计数器,直接在 componentWillMount 中的 this
上设置它。如果你需要在树上传达一些东西,你接受一个回调作为道具,然后调用它。
此外 <Item name={item} closeFn={closeFn.bind(null, i)} key={i} />
没有描述任何从项目中取回数据的方法,除了在请求删除时。
我对 React 中的这种模式感到很困惑。我在其他地方看到过它,但它似乎不正确。
给定以下代码:
/** @jsx React.DOM */
var React = window.React = require('react'),
Item = require("./ui/Item");
var ItemApp = React.createClass({
getInitialState: function() {
return {
items: [ "Example Item" ] // we want one thing to render initially
}; // so prepopulate with one thing
},
getDefaultProps: function () {
return {
index: 1
}
},
onAddItem: function (e) {
var debts = this.state.debts.push( "New Item " + this.props.index);
this.setState({ items: this.state.items });
this.props.index++;
},
onRemoveItem: function (i) {
// splice here
this.state.items.splice(i, 1);
this.setState({ items: this.state.items });
this.props.index--;
},
render: function () {
var items = this.state.items;
var closeFn = this.onRemoveItem;
return (
<div className="col-lg-12">
<div className="cold-md-3"></div>
<div className="col-md-3 col-md-offset-9">
<button type="button" className="btn btn-default" onClick={this.onAddItem}><span className="glyphicon glyphicon-plus"></span> Add New Debt</button>
</div>
{items.map(function (item, i) {
return <Item name={item} closeFn={closeFn.bind(null, i)} key={i} />;
})}
</div>
);
}
});
上面的示例按预期工作(它是一个列表,您可以随意添加和删除内容)但是每当我添加内容时都会重新呈现整个内容。
所以只加了一个组件整个渲染了3次。单击两次后,它将渲染 5 次。您可以看到为什么这可能是个问题。
这看起来效率很低,有更好的方法吗?
如果您想手动管理 dom,React 可能不适合您。如果你真的愿意,你总是可以比抽象做得更好。
在 React 中,通常最好的目标是能够清楚地表达其 React 意图的代码,并让它做它的事情。
您的代码很接近,唯一的问题是您的 key
属性不能唯一地反映数组中的项目。当你有一个堆栈时,基于索引的键是 100% 好的。我给了一个类似的问题
要在这里真正解决这个问题,因为任何项目都可以随时删除,所以您需要在项目本身中编码一个唯一标识符。您应该存储一个对象数组 [{id: '1', text: "a"}, {id: '2', text: "b"}, {id: '3', text: "c"}]
,而不是存储一个字符串数组 ["a", "b", "c"]
。然后你可以使用这个id作为你的密钥,这样会更有效率。
这与问题无关,但是this.props.index--
是在修改道具,这很糟糕而且不可靠。如果你因为某些原因需要保留一个计数器,直接在 componentWillMount 中的 this
上设置它。如果你需要在树上传达一些东西,你接受一个回调作为道具,然后调用它。
此外 <Item name={item} closeFn={closeFn.bind(null, i)} key={i} />
没有描述任何从项目中取回数据的方法,除了在请求删除时。