I was debugging an issue with my ionic 2 app and it turned out that the issue was related to the way ionic instantiates each page several times!
To see what I mean, create a new ionic 2 app from sidemenu template
ionic start app1 sidemenu --v2
then add the following in src/pages/page1/page1.html right after <ion-content padding>
<ion-content padding>
{{ test() }}
then add the test() function in src/pages/page1/page1.ts
test() {
console.log('page1');
}
now build and run the app. you will see once the page1 is loaded there are 11 “page1” loged in the browser console!
Now click on menu icon and open the sidemenu, there are two more “page1” messages!
Select Page2: 4 more “page1” messages!
Go back to Page1: 8 more “page1” messages!
I’m wondering if this excessive template initiation wouldn’t affect on the performance? In my case, I was invoking a heave component in my page and were expecting that the component only instantiates once, but I was getting many copies of that component in the memory due to this issue.
The fact that your {{ test() }} template expression is evaluated 11 times doesn’t mean that the ion-content component is instantiated 11 times. To see how many times the component is instantiated put the logging in the component constructor. (You’ll only see one message in that case.)
Template expressions are evaluated whenever Angular runs it change detection, and the fact that you’re evaluating a method rather than a simple property means Angular needs to call that method every time to check if its return value has changed since the last time.
Thank you mirkonasato for the answer. So I guess this is an Angular issue but how can I avoid instantiating my components that are invoked inside the <ion-content> many times?
Say, you have a <my-calc> component tag inside <ion-content> which does heavy calculation or even http access to retrieve data. According to my test, the my-calc is invoked many times which slows down the app.
What is the best practice in this case?
Again, it’s not your component that’s getting instantiated many times, the component is only instantiated once. It’s template expressions that are evaluated at every change detection.
That’s normal, it’s not something you usually need to worry about. Change detection just means Angular will compare the value of an expression with its previous value to see if it needs to update what’s displayed on the page.
But yes you should avoid doing heavy calculations in a method used in a template expression, and prefer reading properties rather than calling methods in template expressions. HTTP requests are not a problem because they’re async so they don’t block the UI.
Thanks again. It helps a lot. Sorry I don’t mean to ask too much but would appreciate your input on my issue.
In my case, I am calling a method in my component template to get a calculated value to display based on the other Input parameters:
<div>{{ getValue() }}</div>
Now what I’m seeing is that the getValue() is called many times, which according to what you said, is by design. So the question is what is the best practice in this case to avoid recalculation. One way I can think of is the store the current value of Input parameters and in my getValue() function, first compare the new value with old values and only run the calculation if something is changed. Is there a better way?
It pulls some data from the server based on input parameters, filter them and calculates the average, and currently it runs it over 10 times when that page is accessed.
It makes an HTTP request to the server every time a property changes? You could use Observable.debounce to rate-limit whatever event is triggering your request, but it’s difficult to give precise recommendations without knowing exactly what you’re doing.