موضوع این مقاله استفاده مستقیم از توابع و عملیات محاسباتی برای Binding در View میباشد که در پروژههای بزرگ که حجم المنتها در صفحه زیاد است عملکردی منفی در Performance دارد که قابل چشم پوشی نیست. برای اینکه این مورد ملموس باشد بنده مثالی را آماده کردهام که هدف آن بیشتر درک درست شما از این موضوع است.
کد زیر را مشاهده کنید:
<input type="text" ng-model="newItemTitle">
<button type="button" ng-click="add()">افزودن</button>
<ul>
<li ng-repeat="item in items">{{item.title}}</li>
</ul>
<div ng-show="showMSG()">شما بیش از ۱۰ استان ثبت کرده اید</div>
و قسمت Controller:
$scope.newItemTitle='';
$scope.add=function(){
$scope.items.push({
title:$scope.newItemTitle
});
}
$scope.items=[
{title:'اردبیل'},
{title:'تهران'},
{title:'اصفهان'},
{title:'شیراز'},
{title:'مشهد'},
];
$scope.showMSG=function(){
return $scope.items.length>10;
}
همانطور که مشاهده میکنید این کد یک مثال ساده است که شامل لیست استانها و قسمتی برای افزودن استان جدید و در قسمت پایینتر در صورتی که بیش از ۱۰ استان ثبت شده باشد به کاربر پیغامی نمایش میدهیم.
سوال اول، مشکل کجاست؟
این کد کاملا صحیح است، اما بهینه نیست. مشکل اصلی در View است که مستقیما تابع showMSG را صدا میزند. صدا زدن مستقیم توابع از View در قسمتهایی که Bind شدهاند، در Performance نتیجه منفی دارند. منظور از صدا زدن مستقیم توابع در قسمتهای Bind روشهای زیر است:
ng-show="showMSG()"
ng-if="showMSG()"
ng-hide="showMSG()==false"
ng-class="{'red',getResult()}"
ng-style="{'width':getWidth()}"
سوال دوم، چرا Performance را کاهش میدهد؟ AngularJS برای اینکه بتواند تکلیف ng-show هایی را که در div نوشته شدهاست، مشخص کند، مجبور است تابع showMSG را صدا بزند. تا این قسمت هیچ مشکلی نیست. اما وقتی که AngularJS میخواهد در زمانهای بعدی هم متوجه تغییرات بشود مجبود هست دوباره تابع showMSG را صدا بزند و این کار تکرار میشود و در مواقعی که تغییرات انجام شده هیچ ارتباطی با این Binding ندارند باز هم اجرا میشود و این تداوم در اجرا که اکثرا لازم نیستند باعث کاهش Performance میشود. حالا فرض کنید در پروژهای بزرگ در بیشتر قسمتهای صفحه از این روش استفاده کرده اید و پروژه با دادههای حجیم کار میکند.
سوال سوم، راهکار چیست؟
راهکار این موضوع خیلی ساده است؛ اما در بهبود کارآیی پروژه، خیلی تاثیر مثبتی دارد. به طور کلی سعی کنید در Bindingهای View از متغییر استفاده کنید و هیچ تابعی و یا عملیات محاسباتی را در Binding قرار ندهید . منظور از عملیات محاسباتی در Binding روش زیر است:
<div ng-show="items.length>10">شما بیش از ۱۰ استان ثبت کرده اید</div>
حتی این روش هم مناسب نیست. روشی که میتوان برای حل این مشکل در نظر گرفت به شرح زیر است:
$scope.maxItem=false';
$scope.add=function(){
$scope.items.push({
title:$scope.newItemTitle
});
$scope.maxItem=$scope.items.length>10;
}
<div ng-show="maxItem">شما بیش از ۱۰ استان ثبت کرده اید</div>
این مشکل با متفیر maxItem و انتقال منطق به تابع add حل میشود.
نتیجه گیری کلی، در پروژههایی که با دادههای حجیم کار میکنند، هیچ وقت از توابع و عملیات محاسباتی در View استفاده نکنید.