Javascript 以增量方式渲染子对象
假设我有一个React元素Javascript 以增量方式渲染子对象,javascript,reactjs,Javascript,Reactjs,假设我有一个React元素,我需要呈现一个 我的代码目前看起来像 Parent = React.createClass({ getChildren() { var children = this.props.messages; // this could be 100's return children.map((child) => { return <FooBar c={child} />; });
,我需要呈现一个
我的代码目前看起来像
Parent = React.createClass({
getChildren() {
var children = this.props.messages; // this could be 100's
return children.map((child) => {
return <FooBar c={child} />;
});
},
render() {
return (
<div>
{this.getChildren()}
</div>
);
}
});
Parent=React.createClass({
getChildren(){
var children=this.props.messages;//这可能是100
返回children.map((child)=>{
返回;
});
},
render(){
返回(
{this.getChildren()}
);
}
});
当有100个子对象时,这非常慢,因为父对象等待所有子对象渲染。是否有一种解决方法以增量方式渲染子级,以便父级不必等待其所有子级渲染?您可以一次获取一部分消息进行渲染,然后通过状态计数与更多子级一起排队进行进一步更新
对队列使用requestIdleCallback
或setTimeout
将允许您避免React的状态批处理拦截当前浏览器绘制,如果您直接从componentDidUpdate
这里有一些东西可以让你走
const Parent = React.createClass({
numMessagesPerRender = 10
constructor(props) {
super(props)
this.state = {
renderedCount: 0
}
}
componentWillReceiveProps(props) {
// must check that if the messages change, and reset count if you do
// you may also need to do a deep equality of values if you mutate the message elsewhere
if (props.messages !== this.props.messages) {
this.setState({renderedCount: 0})
}
}
getChildren() {
// take only the current
const children = this.props.messages.slice(0, this.state.renderedCount);
return children.map(child => <FooBar c={child} />);
},
render() {
return (
<div>
{this.getChildren()}
</div>
);
}
renderMoreMessagesPlease() {
// you MUST include an escape condition as we are calling from `componentDidXYZ`
// if you dont your component will get stuck in a render loop and crash
if (this.state.renderedCount < this.props.messages.length) {
// queue up state change until the frame has been painted
// otherwise setState can halt rendering to do batching of state changes into a single
// if your browser doesnt support requestIdleCallback, setTimeout should do same trick
this.idleCallbackId = requestIdleCallback(() => this.setState(prevState => ({
renderedCount: prevState.renderedCount + this.numMessagesPerRender
})))
}
}
componentDidMount() {
this.renderMoreMessagesPlease()
}
componentDidUpdate() {
this.renderMoreMessagesPlease()
}
componentDidUnmount() {
// clean up so cant call setState on an unmounted component
if (this.idleCallbackId) {
window.cancelIdleCallback(this.idleCallbackId)
}
}
});
const Parent=React.createClass({
numMessagesPerRender=10
建造师(道具){
超级(道具)
此.state={
RenderCount:0
}
}
组件将接收道具(道具){
//必须检查消息是否更改,如果更改,则重置计数
//如果在其他地方对消息进行变异,则可能还需要执行值的深度相等
if(props.messages!==this.props.messages){
this.setState({renderedCount:0})
}
}
getChildren(){
//只取电流
const children=this.props.messages.slice(0,this.state.renderdcount);
返回children.map(child=>);
},
render(){
返回(
{this.getChildren()}
);
}
RenderMemessagesPlease(){
//当我们从'componentDidXYZ'调用时,必须包含转义条件`
//如果不这样做,组件将卡在渲染循环中并崩溃
if(this.state.renderdcountthis.setState(prevState=>({
RenderCount:prevState.RenderCount+this.numMessagesPerRender
})))
}
}
componentDidMount(){
这个.renderMemessagesPlease()
}
componentDidUpdate(){
这个.renderMemessagesPlease()
}
componentDidUnmount(){
//清理,以便无法在未安装的组件上调用setState
if(this.idleCallbackId){
window.cancelIdleCallback(this.idleCallbackId)
}
}
});
我认为解决这一问题的方法是窗口化,对不起,我忘了提及,但这是我已经实施的解决方案,但感觉不太正确,我想知道是否有更简单的解决方案。更好的解决方案可能更以用户界面为中心,通过这种方式,呈现的消息量与用户在任何时候实际看到的内容相关联,即如果用户需要滚动查看完整列表,则只呈现项目,直到它们变得不可见,然后使用滚动事件在状态中触发此额外消息计数。它将使用与此类似的机制,而是使用requestAnimationFrame
在屏幕绘制之前进行拦截,测量渲染消息的大小,与可用的可见空间进行比较,并排队进行更多渲染,直到它们变得不可见