我想问一下快速渲染的正确方法> React中有10000件商品。
假设我想创建一个checkboxList,包含动态10000复选框项。
我创建了一个包含所有项目的商店,它将用作复选框列表的状态。
当我点击任何复选框项目时,它会按操作更新相应的项目,因此商店会更改。
由于商店已更改,因此会触发复选框列表更新。
复选框列表更新其状态并再次渲染。
这里的问题是,如果我点击任何复选框项目,我必须等待>勾选复选框3秒钟。我不希望这只需要重新渲染一个复选框项。
我试图找到根本原因。 最耗时的部分是在复选框列表渲染方法中,与.map相关,它创建Checkbox组件以形成componentList .. 但实际上只有1个复选框必须重新渲染。
以下是我的代码。 我使用ReFlux作为助焊剂架构。
CheckboxListStore
商店将所有复选框项目存储为地图。 (名称为键,状态(true / false)为值)
const Reflux = require('reflux');
const Immutable = require('immutable');
const checkboxListAction = require('./CheckboxListAction');
let storage = Immutable.OrderedMap();
const CheckboxListStore = Reflux.createStore({
listenables: checkboxListAction,
onCreate: function (name) {
if (!storage.has(name)) {
storage = storage.set(name, false);
this.trigger(storage);
}
},
onCheck: function (name) {
if (storage.has(name)) {
storage = storage.set(name, true);
this.trigger(storage);
}
},
onUncheck: function (name) {
if (storage.has(name)) {
storage = storage.set(name, false);
this.trigger(storage);
}
},
getStorage: function () {
return storage;
}
});
module.exports = CheckboxListStore;
CheckboxListAction
操作,创建,检查和取消选中任何带有名称的复选框项。
const Reflux = require('reflux');
const CheckboxListAction = Reflux.createActions([
'create',
'check',
'uncheck'
]);
module.exports = CheckboxListAction;
的CheckBoxList
const React = require('react');
const Reflux = require('reflux');
const $ = require('jquery');
const CheckboxItem = require('./CheckboxItem');
const checkboxListAction = require('./CheckboxListAction');
const checkboxListStore = require('./CheckboxListStore');
const CheckboxList = React.createClass({
mixins: [Reflux.listenTo(checkboxListStore, 'onStoreChange')],
getInitialState: function () {
return {
storage: checkboxListStore.getStorage()
};
},
render: function () {
const {storage} = this.state;
const LiComponents = storage.map((state, name) => {
return (
<li key = {name}>
<CheckboxItem name = {name} />
</li>
);
}).toArray();
return (
<div className = 'checkbox-list'>
<div>
CheckBox List
</div>
<ul>
{LiComponents}
</ul>
</div>
);
},
onStoreChange: function (storage) {
this.setState({storage: storage});
}
});
module.exports = CheckboxList;
CheckboxItem 在onChange回调中,我调用动作来更新项目。
const React = require('react');
const Reflux = require('reflux');
const $ = require('jquery');
const checkboxListAction = require('./CheckboxListAction');
const checkboxListStore = require('./CheckboxListStore');
const CheckboxItem = React.createClass({
mixins: [Reflux.listenTo(checkboxListStore, 'onStoreChange')],
propTypes: {
name: React.PropTypes.string.isRequired
},
getInitialState: function () {
const {name} = this.props;
return {
checked: checkboxListStore.getStorage().get(name)
};
},
onStoreChange: function (storage) {
const {name} = this.props;
this.setState({
checked: storage.get(name)
});
},
render: function () {
const {name} = this.props;
const {checked} = this.state;
return (
<div className = 'checkbox' style = {{background: checked ? 'green' : 'white'}} >
<span>{name}</span>
<input ref = 'checkboxElement' type = 'checkbox'
onChange = {this.handleChange}
checked = {checked}/>
</div>
);
},
handleChange: function () {
const {name} = this.props;
const checked = $(this.refs.checkboxElement).is(':checked');
if (checked) {
checkboxListAction.check(name);
} else {
checkboxListAction.uncheck(name);
}
}
});
module.exports = CheckboxItem;
答案 0 :(得分:2)
您可以采取一些方法:
storage.toArray().map(...)
(这样您就不会创建中间映射),甚至更好,制作并清空数组,然后执行storage.forEach(...)添加元素推 - 快得多。但是,React diffing算法仍然需要对10000个元素进行区分,这种方法永远不会很快,但是生成元素的代码要快得多。将自定义shouldComponentUpdate添加到CheckboxList:
shouldComponentUpdate:function(nextProps, nextState) {
var storage = this.state.storage;
var nextStorage = nextState.storage;
if (storage.size !== nextStorage.size) return true;
// check item names match for each index:
return !storage.keySeq().equals(nextStorage.keySeq());
}
答案 1 :(得分:1)
答案 2 :(得分:1)
除了初始渲染之外,您还可以使用Mobservable显着提高大型集合的渲染速度。当孩子通过自动应用副作用加载进行更改时,它可以避免重新渲染映射到10.000个项目的父组件。有关详细说明,请参阅此blog。
答案 3 :(得分:0)
你的渲染功能看起来有点复杂,需要:
.toArray()
将渲染函数简化为类似的东西可能会有所帮助吗?
render: function () {
return (
<div className = 'checkbox-list'>
<div>
CheckBox List
</div>
<ul>
{this.state.storage.map((state, name) => {
return (
<li key = {name}>
<CheckboxItem name = {name} />
</li>
);
})}
</ul>
</div>
);
},
答案 4 :(得分:0)
每次检查/取消选中时,您是否真的需要在商店中保存支票状态?
我最近遇到了和你一样的问题。只需在CheckboxList组件的状态中保存checkedList数组[name1,name2 ...],并在每次选中/取消选中项目时更改此checkedList。如果要将检查状态保存到数据存储,请调用Action.save()并将checkedList传递给存储 但是,如果每次检查/取消选中时确实需要保存到数据存储,此解决方案将无法帮助-_-。