-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
files-list: performance optimizations #40958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,9 +22,9 @@ | |
| <template> | ||
| <span class="files-list__row-icon"> | ||
| <template v-if="source.type === 'folder'"> | ||
| <FolderOpenIcon v-if="dragover" /> | ||
| <FolderOpenIcon v-once v-if="dragover" /> | ||
| <template v-else> | ||
| <FolderIcon /> | ||
| <FolderIcon v-once /> | ||
| <OverlayIcon :is="folderOverlay" | ||
| v-if="folderOverlay" | ||
| class="files-list__row-icon-overlay" /> | ||
|
|
@@ -41,13 +41,13 @@ | |
| @error="backgroundFailed = true" | ||
| @load="backgroundFailed = false"> | ||
|
|
||
| <FileIcon v-else /> | ||
| <FileIcon v-once v-else /> | ||
|
|
||
| <!-- Favorite icon --> | ||
| <span v-if="isFavorite" | ||
| class="files-list__row-icon-favorite" | ||
| :aria-label="t('files', 'Favorite')"> | ||
| <FavoriteIcon /> | ||
| <FavoriteIcon v-once /> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Icons don't need re-rendering |
||
| </span> | ||
| </span> | ||
| </template> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -259,18 +259,17 @@ export default Vue.extend({ | |
| event.preventDefault() | ||
| event.stopPropagation() | ||
|
|
||
| // If reaching top, scroll up | ||
| const firstVisible = this.$refs.table?.$el?.querySelector('.files-list__row--visible') as HTMLElement | ||
| const firstSibling = firstVisible?.previousElementSibling as HTMLElement | ||
| if ([firstVisible, firstSibling].some(elmt => elmt?.contains(event.target as Node))) { | ||
| const tableTop = this.$refs.table.$el.getBoundingClientRect().top | ||
| const tableBottom = tableTop + this.$refs.table.$el.getBoundingClientRect().height | ||
|
|
||
| // If reaching top, scroll up. Using 100 because of the floating header | ||
| if (event.clientY < tableTop + 100) { | ||
| this.$refs.table.$el.scrollTop = this.$refs.table.$el.scrollTop - 25 | ||
| return | ||
| } | ||
|
|
||
| // If reaching bottom, scroll down | ||
| const lastVisible = [...(this.$refs.table?.$el?.querySelectorAll('.files-list__row--visible') || [])].pop() as HTMLElement | ||
| const nextSibling = lastVisible?.nextElementSibling as HTMLElement | ||
| if ([lastVisible, nextSibling].some(elmt => elmt?.contains(event.target as Node))) { | ||
| if (event.clientY > tableBottom - 50) { | ||
| this.$refs.table.$el.scrollTop = this.$refs.table.$el.scrollTop + 25 | ||
| } | ||
| }, | ||
|
|
@@ -312,6 +311,8 @@ export default Vue.extend({ | |
| &::v-deep { | ||
| // Table head, body and footer | ||
| tbody { | ||
| will-change: scroll-position, padding; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about padding. Is it even a valid value for
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well |
||
| contain: layout paint style; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some CSS tricks to improve rendering performance |
||
| display: flex; | ||
| flex-direction: column; | ||
| width: 100%; | ||
|
|
@@ -320,6 +321,7 @@ export default Vue.extend({ | |
|
|
||
| /* Hover effect on tbody lines only */ | ||
| tr { | ||
| contain: strict; | ||
| &:hover, | ||
| &:focus { | ||
| background-color: var(--color-background-dark); | ||
|
|
@@ -329,6 +331,7 @@ export default Vue.extend({ | |
|
|
||
| // Before table and thead | ||
| .files-list__before { | ||
| contain: strict; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,6 @@ | |
| <component :is="dataComponent" | ||
| v-for="({key, item}, i) in renderedItems" | ||
| :key="key" | ||
| :visible="(i >= bufferItems - 1 || index <= bufferItems) && (i <= shownItems - bufferItems)" | ||
| :source="item" | ||
| :index="i" | ||
| v-bind="extraProps" /> | ||
|
|
@@ -211,7 +210,7 @@ export default Vue.extend({ | |
| } | ||
|
|
||
| // Adding scroll listener AFTER the initial scroll to index | ||
| this.$el.addEventListener('scroll', this.onScroll) | ||
| this.$el.addEventListener('scroll', this.onScroll, { passive: true }) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passive listeners are faster |
||
|
|
||
| this.$_recycledPool = {} as Record<string, any> | ||
| }, | ||
|
|
@@ -232,11 +231,14 @@ export default Vue.extend({ | |
| }, | ||
|
|
||
| onScroll() { | ||
| const topScroll = this.$el.scrollTop - this.beforeHeight | ||
| const index = Math.floor(topScroll / this.itemHeight) * this.columnCount | ||
| // Max 0 to prevent negative index | ||
| this.index = Math.max(0, index) | ||
| this.$emit('scroll') | ||
| this._onScrollHandle ??= requestAnimationFrame(() => { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Throttling this call to once per frame. Notably,
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's something I wanted to experiment with! Nice take at this issue! It make sense :) |
||
| this._onScrollHandle = null; | ||
| const topScroll = this.$el.scrollTop - this.beforeHeight | ||
| const index = Math.floor(topScroll / this.itemHeight) * this.columnCount | ||
| // Max 0 to prevent negative index | ||
| this.index = Math.max(0, index) | ||
| this.$emit('scroll') | ||
| }); | ||
| }, | ||
| }, | ||
| }) | ||
|
|
||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing import