Q-table Slow conditional rendering
I have experienced slower rendering when using conditional rendering of the q-table.
When extening to All the table renders quite slow, the more columns there are, it seems every conditionally rendered column decreases the speed by around 1s in this case.
Also it seems to me the more complex the conditional render is, the slower it renders (slower when using q-tooltip, than other)
Here is a example of the slow rendering (expand to all rows, measure time):
what can i do about that?
After looking at Qtooltip it seems it’s causing a force re-render on the mounted() hook. This was initially added as google chrome workaround. Here’s a link to line of code causing this.
This line of code forces layout re-flow in browsers. Here’s a quick link on what causes layout re-flow.
Using your example and commenting that line out still worked even on latest chrome so not sure why they used this (maybe earlier version of chrome was causing some weird behaviour) and even if needed, not sure why they removed child node and not just set display non on that.
Hope someone from the dev team gets on your issue. In the meantime maybe you can fallback to title html tag instead of qtooltip.
This decreased the rendering time a bit in my application(not the example) from 14s to 8s. still this is to long compared against the 2s using it without conditional table cell rendering.
I would really like to help here, to reproduce it and give you some examples.
Question: is there a way i can trace the time for the table to be re-rendered? i tried to watch pagination change but the change is triggered before the time intensive stuff happens and then i dont know where to stop the timer.
Is there a way to at least display the table loading while the rendering process is working (start render event, end render event)?
What i can see currently is that the whole browser is hanging while the rendering is happening (loading to true, hangs the loading bar, …)
What i can already say is that its not the filter and sort method which take the time!
s.molinari last edited by
@rstoenescu - can you have a look at this?
just wanted to ask how i can help with the issue
The problem you are facing is not related to quasar, beside the qtooltip component which needs to be fixed, but it’s actually how vue works and renders components. You are trying to render each and every component in the body at once (which means lets say you have 500 rows with 10 columns, that equals to 5000 components being rendered from qbtn, qtooltip, qtd etc…) all at the same time.
But here’s what might be done to make this faster.
First if you are not modifying the data object then freeze it with Object.freeze(). Read on vue js docs to know how.
Another thing I would do is to fallback to non component stuff inside your table body. Check out this codpen of your example to get an idea of what i mean. (But this might break how things are styled across other platforms so i would be very carfeull with this one and use correct styling, the one in the example i gave is just a quick test)
One last thing that you can check out is the vue virtual scroller. I don’t know if this plays well with Quasar, you will have to test it out.
Thanks a lot for the info…
Freeze helped a bit, but with not using components it doesnt help much to reduce the speed.
Is there any hook where i can tap into to measure the performance of the render process (start and end)?
I would like to build this table with a few options so i can trace the bottlenecks and throw out stuff/replace it.
I usually use chrome/firefox and record the performance while testing the part I need to test and if you’re using vue 2.2.0+ you can get advangtage of the user timing api. Here’s a link from vue.js docs on that.
By simply placing this line in your code
Vue.config.performance = true, it will enable vue performance tracing. Then using chrome dev tools you can record the performance while doing your test and then go through the report generated to find the bottleneck.
Here’s a good article on that matter from medium, it can get you started. Also, you might need to read a bit about runtime performance if you haven’t used it before, it’s a very powerfull tool and can let you simulate performance on slower devices. If using chrome dev tools, here’s a quick link from their docs.
PS: There’s an extension that you can also use as well, it’s called vue performance(chrome/firefox) I haven’t used it much but It might also help.
Thanks for the help!
So what i have seen in my case (260 rows/ 9 Visible columns):
- Basic table without checkboxes: 145 ms vue <QTable> patch
- Basic table with checkboxes: 1.12 s vue <QTable> patch (QCheckbox -> init, render, patch)
- Basic table with QTd and checkboxes: 5.6 s vue <QTable> patch (QCheckbox, QTd, QBtn, QIcon, … -> init, render, patch)
All of the QCheckbox, QBtn, … are taking between a few us till 20 ms
Keep in mind iam running the dev version here.
So i can practically confirm your description with all the components beeing rendered.
Is there any way i can pre-render the components in the row so i can maybe use the html directly with all the classes, etc… Somehow this could increase the performance drastically without sacrificing the usefulness of them. The best thing would be if we dont have to render the Qtd too.
This performance stuff is related to how vue works (MVVM libraries in general). In which they need to create an instance for every component you are trying to render in the loop and set bindings to it). This is important for vue to be reactive and update those components fast. This is a famous issue with vue and here’s a quick link from that issue on vuejs git repo, read the whole thing, it sheds the light a bit on what workarounds can be used in such cases.
In brief, if you don’t need vue’s reactivity on this part of your app then you should use something else like handlebars… Or maybe try and create statless functional components. For that you will need to create your own table components and then use them with Q-Table. (I don’t know how much that would imporve performance but is should)
I understand that problem now but either way iam a bit hesitant of what i should do now. I dont need them to be reactive, but i dont actually want to revwrite components which have a certain look and feel and some functionality (button, icon, select, …) given by the framework, which will only result in a lot of work and changes made in the framework (style, functionality) will never be reflected in those components.
Is there a way to convert a quasar component to a non reactive component (i know this sounds stupid) by overriding some functions and props?
Especially the QBtn and QIcon would be great.
I also struggled with many components inside QTable. I replaced them using native html with quasar css:
<button tabindex=“0” type=“button” class=“q-btn inline relative-position q-btn-item non-selectable q-btn-rectangle q-focusable q-hoverable bg-white text-black”><div class=“q-focus-helper”></div><div class=“q-btn-inner row col items-center justify-center”><div>Standard</div></div></button>
This is not good long term solution but I agree that we need some functional components built in into framework - for exapmle: QBtnSimple, QIconSimple etc… This way we can avoid that future change inside framework css will break my native button styled using quasar css. I will create feature request for that using Github. Not everyone knows at the beginning why some components work so slowly using sub components.