quasar
quasar copied to clipboard
Functions inside qscrollarea keeps getting called over and over when scrollbar changes (visibility or movement)
What happened?
So I'm noticing odd function call behavior inside a qscrollarea. It seems anytime I mouse over the scroll area the function gets called which is not what happened in v1. Computed behaves as expected. And you don't even have to scroll. Just mouse enter and leave and you'll see the function get hit. How do I revert back to how v1 behaved or is this some odd vue 3 reactivity interaction I'm not understanding. It seems to be tied to scroll bar. If I set it to visible I can mouse over and out all day and it won't trigger b/c the scroll bar isn't fading in and out. Unfortunately, moving the scroll bar will also trigger the function call.
What did you expect to happen?
I expected it to not constantly call functions inside qScrollArea. Quasar v1 does not exhibit this behavior.
Reproduction URL
https://codepen.io/aroganx/pen/gOqWgBY
How to reproduce?
Run the codepen and just mouse over in and out of scroll area. Scrolling in the scroll area will also cause the function to get called repeatedly.
Flavour
Quasar CLI with Webpack (@quasar/cli | @quasar/app-webpack)
Areas
Components (quasar)
Platforms/Browsers
Chrome
Quasar info output
Operating System - Windows_NT(10.0.22621) - win32/x64
NodeJs - 18.17.1
Global packages
NPM - 9.8.1
yarn - 1.22.19
@quasar/cli - 2.2.3
@quasar/icongenie - Not installed
cordova - Not installed
Important local packages
quasar - 2.12.5 -- Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
@quasar/app-webpack - 3.9.6 -- Quasar Framework App CLI with Webpack
@quasar/extras - 1.16.6 -- Quasar Framework fonts, icons and animations
eslint-plugin-quasar - Not installed
vue - 3.3.4 -- The progressive JavaScript framework for building modern web UI.
vue-router - 4.2.4
pinia - Not installed
vuex - 4.1.0 -- state management for Vue.js
electron - Not installed
electron-packager - Not installed
electron-builder - Not installed
@babel/core - 7.22.11 -- Babel compiler core.
webpack - 5.88.2 -- Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
webpack-dev-server - 4.11.1 -- Serves a webpack app. Updates the browser on changes.
workbox-webpack-plugin - Not installed
register-service-worker - 1.7.2 -- Script for registering service worker, with hooks
typescript - 4.9.4 -- TypeScript is a language for application scale JavaScript development
@capacitor/core - Not installed
@capacitor/cli - Not installed
@capacitor/android - Not installed
@capacitor/ios - Not installed
Quasar App Extensions
@quasar/quasar-app-extension-qcalendar - 4.0.0-beta.16 -- A Quasar App Extension for @quasar/quasar-ui-qcalendar
@toby.mosque/quasar-app-extension-qdatetimepicker - 2.0.0-rc.3 -- Quasar Date Time Picker Extension
@quasar/quasar-app-extension-qmarkdown - 2.0.0-beta.10 -- Display inline markdown in your Quasar App
Relevant log output
testComputed: 1
testFx: 16
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
Additional context
No response
If you want to call functions inside the content then put your content in a component, so that vue can optimize the rendering
Extracting everything inside q-scroll-area into a separate component does indeed solve the issue. It's still not ideal as I have about 10 places I need to do this and it requires creating a new component, and extracting out logic into a mixin. But it's a path forward.
Strangely search didn't pick up this one. Copying the suggestions over from my report:
Since all the computed value updates relate to thumb display, the straight forward solution would be to pull out the thumb rendering logic into pure JS world. I also suspect there is a way to rewrite the render function (rather than relying on the compiler) using vnode creation calls to mark the child nodes (ones inserted via the slot) as isolated from thumb-related nodes.
If you want to call functions inside the content then put your content in a component, so that vue can optimize the rendering
Separate component does not solve the underlying issue: Vue will still invoke the render function of that separate component for every value update inside QScrollArea.
Known workaround
For those that are seeking a workaround, you can use v-memo or v-once on your components rendered within QScrollArea. But make sure you understand how they behave, before using them in production.
Hi! I am building a component based on QScrollArea and I've encountered the same performance issue highlighted by @thexeos here and in #16813 and #17041. The biggest concern is the re-rendering of every component during scroll.
I've tried both v-once and v-memo on content inside the default slot but it keeps getting rerendered. The difference is obviously noticeable if i don't use components at all.
Hope the PR gets merged soon :smile: , for now i'll use a simple scrolling div instead of QScrollArea.