در اینجا ما کامپوننت Datagrid>> روال render() را طراحی اپلیکیشن داریم:
// in Datagrid.js
render() {
const {
resource,
children,
ids,
data,
currentSort
} = this.props;
return (
{Children.map(children, (field, index) =>
key={index}
field={field}
currentSort={currentSort}
updateSort={this.updateSort}
/>
)}
{ids.map(id => (
{Children.map(children, (field, index) =>
record={data[id]}
key={`${id}-${index}`}
field={field}
resource={resource}
/>
)}
))}
);
}
به حیث میرسد کهاین شغل یک پیادهسازی بی آلایش از datagrid میباشد، با این اکنون بسیار ناکارآمد میباشد.هر فراخوانی DatagridCell>> دست کم دو یا این که سه کامپوننت را رندر مینماید. به عبارتیطور که در اسکرینشات اول می بینید، لیست 7 ردیف، 11 سطر دارااست، کهاین یعنی 231 = 7*11*3 کامپوننت رندر گردیده. هنگامی تنها currentSort تغییرو تحول مینماید، در واقع این عمل یک اتلاف وقت میباشد.
حتی با اینکه React، در صورتیکه VirtualDom رندر گردیده تغییر و تحول نکرده باشد، DOM حقیقی و واقعی را آپ دیت نمینماید، گشوده هم 500ms برای پردازش همگی کامپوننتها مجال میبرد.
برای اجتناب از رندرهای غیرضروری بدنه جدول، می بایست آغاز آن را استحصال کنیم:
// in Datagrid.js
render() {
const {
resource,
children,
ids,
data,
currentSort
} = this.props;
return (
{React.Children.map(children, (field, index) =>
key={index}
field={field}
currentSort={currentSort}
updateSort={this.updateSort}
/>
)}
{children}
);
);
}
ما یک کامپوننت تازه را بوسیله دستیابی منطق بدنه جدول تولید کردهایم:
// in DatagridBody.js
import React, { Children } from \'react\';
const DatagridBody = ({ resource, ids, data, children }) => (
{ids.map(id => (
{Children.map(children, (field, index) =>
record={data[id]}
key={`${id}-${index}`}
field={field}
resource={resource}
/>
)}
))}
);
export default DatagridBody;
کسب بدنه جدول هیچ تاثیری بر عملکرد ندارد، ولی مسیر باصرفهسازی را نماد می دهد. با صرفهسازی کامپوننتهای تبارک و همگانی دشوار میباشد. رمز و شغل داشتن با کامپوننتهای خرد که تک مسئولیتی میباشند بسیار راحتخیس می باشند.
shouldComponentUpdate
مستندسازی React در ارتباط با نحوه خودداری از رندرهای غیرضروری خیلی بدیهی نقل شده میباشد: shouldComponentUpdate(). به صورت پیشفرض، مدام React یک کامپوننت را برای DOM مجازی رندر مینماید. به عبارت دیگر، فعالیت شما تحت عنوان یک گسترشدهنده این میباشد که نظارت نمائید تا propهای کامپوننت تغییرو تحول نکرده باشند و در آن شکل آحاد رندرها را رد فرمایید.
در زمینهی کامپوننت در ابتدا، بدنه نباید رندر خواهد شد مگر اینکه propها عوض شده باشند.
براین اساس کامپوننت می بایست به طور ذیل کامل شدن خواهد شد:
import React, { Children, Component } from \'react\';
class DatagridBody extends Component {
shouldComponentUpdate(nextProps) {
return (nextProps.ids !== this.props.ids
|| nextProps.data !== this.props.data);
}
render() {
const { resource, ids, data, children } = this.props;
return (
{ids.map(id => (
{Children.map(children, (field, index) =>
record={data[id]}
key={`${id}-${index}`}
field={field}
resource={resource}
/>
)}
))}
);
}
}
export default DatagridBody;
نکته: تحت عنوان یک جایگزین برای پیادهسازی دستی shouldComponentUpdate()، میتوانستیم از PureComponent به مکان Component به کارگیری کنیم. این فعالیت کلیه propها را با به کار گیری از آرم تساوی (===) مقایسه کرده و تنها درحالتی که هر prop تغییر و تحول نماید، کامپوننت را رندر مینماید. البته میدانیم که دراینحالت resource وchildren نمیتوانند تغییر و تحول نمایند، به این ترتیب نیازی وجود ندارد تا تساوی آنان را پژوهش کنیم.
با این با صرفهسازی، رندر کامپوننتDatagrid>> بعداز کلیک روی هدر جدول، بدنه جدول و 231 کامپوننت آن را تماما رد مینماید. این شغل مجال آپ تو دیت را از 500ms به 60ms کاهش میدهد که یک توسعه کوشش فراتر از 400ms میباشد!
نکته: نگذارید که پهنا نمودار زردرنگ شمارا فریب دهد. این گزینه حتی بیشتر از نمودار پیشین کلان گردیده است. پس مطلقا خوب میباشد.
باصرفهسازی shouldComponentUpdate تعداد متعددی حفره در نمودار رنگ زرد را از در میان می برد و فرصت کلی رندر کردن را کاهش می دهد. ما قادر خواهیم بود از ترفندهای مشابهی برای خودداری از رندرهای بیشتر استعمال کنیم. (به عنوان مثال برای پرهیز از رندر کردن sidebar، دکمههای اقدامات، هدرهای جدول که تغییر تحول نمیکردهاند، ورقه بندی). بعد از حدود یک ساعت شغل، آحاد کاغذ بعداز کلیک روی ردیف هدر تنها در 100ms رندر میشود. این مراحل به اندازه کافی سریع میباشد؛ حتی درصورتی که هنوز هم جا برای با صرفهسازی باشد.
اضافه کردن مشی shouldComponentUpdate ممکن میباشد هنگفت به حیث رسد، البته در شرایطی که همت برای شما اساسی میباشد، تمامی کامپوننتهایی که مینویسید خوب میباشد با یک کدام از آنان مجموع شوند.
این شغل را همگی جا اعمال ندهید. اجرای shouldComponentUpdate بر روی کامپوننتهای معمولی برخی اوقات کندتر از رندر کردن کامپوننت میباشد. این شغل یک باصرفهسازی زود گذر میباشد. البته به عبارتیطور که اپلیکیشنهای شما پرورش مینمایند و میتوانید ضعفهای عملکردی را در کامپوننتهای خویش شناسایی نمائید، منطق shouldComponentUpdate را برای سریعخیس شدن اضافه نمایید.
Recompose
اینجانب به خیال shouldComponentUpdate چندان با تغییرات پیشین بر روی < DatagridBody > موافق نیستم. ما ناچار شدیم یک کامپوننت بی آلایش و عملکردی را به کامپوننتی بر محور کلاس تبدیل کنیم. این عمل خطوط کد بیشتری را اضافه کرده، و هر خط کد برای تایپ کردن، خطایابی، و مراقبت هزینهای دارااست.