mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
fix: avoid many scrollTo calls for n components
Thank you @vbelolapotkov for pointing out the flaws here: https://github.com/Human-Connection/Human-Connection/pull/1756#discussion_r329361572 So here is my attempt to fix it: * Install `vue-scrollto` which relies on `requestAnimationFrame` - apparently this is better on Safari and IE? 🤔 - Mocking out entire modules is easier in jest: https://jestjs.io/docs/en/bypassing-module-mocks * Require `checkAnchor` to be implemented on the component
This commit is contained in:
parent
2c705a8680
commit
9da40c4895
@ -10,7 +10,7 @@
|
|||||||
</ds-card>
|
</ds-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-else :class="{ comment: true, 'disabled-content': comment.deleted || comment.disabled }">
|
<div v-else :class="{ comment: true, 'disabled-content': comment.deleted || comment.disabled }">
|
||||||
<ds-card :id="`commentId-${comment.id}`">
|
<ds-card :id="anchor">
|
||||||
<ds-space margin-bottom="small" margin-top="small">
|
<ds-space margin-bottom="small" margin-top="small">
|
||||||
<hc-user :user="author" :date-time="comment.createdAt" />
|
<hc-user :user="author" :date-time="comment.createdAt" />
|
||||||
<!-- Content Menu (can open Modals) -->
|
<!-- Content Menu (can open Modals) -->
|
||||||
@ -111,6 +111,9 @@ export default {
|
|||||||
user: 'auth/user',
|
user: 'auth/user',
|
||||||
isModerator: 'auth/isModerator',
|
isModerator: 'auth/isModerator',
|
||||||
}),
|
}),
|
||||||
|
anchor() {
|
||||||
|
return `commentId-${this.comment.id}`
|
||||||
|
},
|
||||||
displaysComment() {
|
displaysComment() {
|
||||||
return !this.unavailable || this.isModerator
|
return !this.unavailable || this.isModerator
|
||||||
},
|
},
|
||||||
@ -144,6 +147,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
checkAnchor(anchor) {
|
||||||
|
return `#${this.anchor}` === anchor
|
||||||
|
},
|
||||||
isAuthor(id) {
|
isAuthor(id) {
|
||||||
return this.user.id === id
|
return this.user.id === id
|
||||||
},
|
},
|
||||||
|
|||||||
@ -41,6 +41,9 @@ export default {
|
|||||||
post: { type: Object, default: () => {} },
|
post: { type: Object, default: () => {} },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
checkAnchor(anchor) {
|
||||||
|
return anchor === '#comments'
|
||||||
|
},
|
||||||
updateCommentList(updatedComment) {
|
updateCommentList(updatedComment) {
|
||||||
this.post.comments = this.post.comments.map(comment => {
|
this.post.comments = this.post.comments.map(comment => {
|
||||||
return comment.id === updatedComment.id ? updatedComment : comment
|
return comment.id === updatedComment.id ? updatedComment : comment
|
||||||
|
|||||||
@ -1,32 +1,20 @@
|
|||||||
export function scrollToAnchor(anchor) {
|
import { scrollTo } from 'vue-scrollto'
|
||||||
if (!anchor) return
|
|
||||||
if (!window || !document) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const container = document.querySelector(anchor)
|
|
||||||
if (container) {
|
|
||||||
const { top } = container.getBoundingClientRect()
|
|
||||||
setTimeout(() => {
|
|
||||||
// we have to set a small timeout to ensure this part comes after nuxt
|
|
||||||
// scrollBehaviour: https://nuxtjs.org/api/configuration-router/#scrollbehavior
|
|
||||||
window.scroll({
|
|
||||||
top,
|
|
||||||
left: 0,
|
|
||||||
behavior: 'smooth',
|
|
||||||
})
|
|
||||||
}, 250)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
watch: {
|
watch: {
|
||||||
$route(to, from) {
|
$route(to, from) {
|
||||||
const anchor = to && to.hash
|
const anchor = to && to.hash
|
||||||
scrollToAnchor(anchor)
|
if (!this.checkAnchor(anchor)) return
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollTo(anchor, 1000)
|
||||||
|
}, 250)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const anchor = this.$route && this.$route.hash
|
const anchor = this.$route && this.$route.hash
|
||||||
scrollToAnchor(anchor)
|
if (!this.checkAnchor(anchor)) return
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollTo(anchor, 1000)
|
||||||
|
}, 250)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
47
webapp/mixins/scrollToAnchor.spec.js
Normal file
47
webapp/mixins/scrollToAnchor.spec.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { scrollTo } from 'vue-scrollto'
|
||||||
|
import scrollToAnchor from './scrollToAnchor'
|
||||||
|
jest.mock('vue-scrollto')
|
||||||
|
|
||||||
|
let component
|
||||||
|
|
||||||
|
describe('scrollToAnchor', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers()
|
||||||
|
scrollTo.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('scrollToAnchor', () => {
|
||||||
|
const action = hash => {
|
||||||
|
let {
|
||||||
|
watch: { $route },
|
||||||
|
} = scrollToAnchor
|
||||||
|
$route.bind(component)({ hash })
|
||||||
|
jest.runAllTimers()
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('given anchor `commentId-4711`', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component = {
|
||||||
|
anchor: 'commentId-4711',
|
||||||
|
checkAnchor(anchor) {
|
||||||
|
return this.anchor === anchor
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('$route.hash === anchor', () => {
|
||||||
|
it('calls window.scroll', () => {
|
||||||
|
action('commentId-4711')
|
||||||
|
expect(scrollTo).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('$route.hash !== anchor', () => {
|
||||||
|
it('skips window.scroll', () => {
|
||||||
|
action('commentId-4712')
|
||||||
|
expect(scrollTo).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -83,6 +83,7 @@
|
|||||||
"vue-count-to": "~1.0.13",
|
"vue-count-to": "~1.0.13",
|
||||||
"vue-infinite-scroll": "^2.0.2",
|
"vue-infinite-scroll": "^2.0.2",
|
||||||
"vue-izitoast": "^1.2.1",
|
"vue-izitoast": "^1.2.1",
|
||||||
|
"vue-scrollto": "^2.17.1",
|
||||||
"vue-sweetalert-icons": "~4.2.0",
|
"vue-sweetalert-icons": "~4.2.0",
|
||||||
"vuex-i18n": "~1.13.1",
|
"vuex-i18n": "~1.13.1",
|
||||||
"xregexp": "^4.2.4",
|
"xregexp": "^4.2.4",
|
||||||
|
|||||||
@ -4235,6 +4235,11 @@ bcrypt-pbkdf@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tweetnacl "^0.14.3"
|
tweetnacl "^0.14.3"
|
||||||
|
|
||||||
|
bezier-easing@2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bezier-easing/-/bezier-easing-2.1.0.tgz#c04dfe8b926d6ecaca1813d69ff179b7c2025d86"
|
||||||
|
integrity sha1-wE3+i5JtbsrKGBPWn/F5t8ICXYY=
|
||||||
|
|
||||||
bfj@^6.1.1:
|
bfj@^6.1.1:
|
||||||
version "6.1.1"
|
version "6.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48"
|
resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48"
|
||||||
@ -15315,6 +15320,13 @@ vue-router@~3.0.7:
|
|||||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.7.tgz#b36ca107b4acb8ff5bc4ff824584059c23fcb87b"
|
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.7.tgz#b36ca107b4acb8ff5bc4ff824584059c23fcb87b"
|
||||||
integrity sha512-utJ+QR3YlIC/6x6xq17UMXeAfxEvXA0VKD3PiSio7hBOZNusA1jXcbxZxVEfJunLp48oonjTepY8ORoIlRx/EQ==
|
integrity sha512-utJ+QR3YlIC/6x6xq17UMXeAfxEvXA0VKD3PiSio7hBOZNusA1jXcbxZxVEfJunLp48oonjTepY8ORoIlRx/EQ==
|
||||||
|
|
||||||
|
vue-scrollto@^2.17.1:
|
||||||
|
version "2.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-scrollto/-/vue-scrollto-2.17.1.tgz#cd62ee0b98cf7e2ba9fd94f029addcd093978a48"
|
||||||
|
integrity sha512-uxOJXg6cZL88B+hTXRHDJMR+gHGiaS70ZTNk55fE5Z2TdwyIx9K/IHoNeTrtBrM6u3FASAIymKjZaQLmDf8Ykg==
|
||||||
|
dependencies:
|
||||||
|
bezier-easing "2.1.0"
|
||||||
|
|
||||||
vue-server-renderer@^2.6.10:
|
vue-server-renderer@^2.6.10:
|
||||||
version "2.6.10"
|
version "2.6.10"
|
||||||
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375"
|
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user