Skip to content
This repository was archived by the owner on Jul 1, 2023. It is now read-only.

Commit 3a2dfbc

Browse files
committed
<keep-alive> support
1 parent 418bebf commit 3a2dfbc

File tree

4 files changed

+123
-9
lines changed

4 files changed

+123
-9
lines changed

src/listscroller.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ export default {
156156
* Updates average items' height and corrects spacerMargin
157157
*/
158158
onItemsResize(entities) {
159+
if (this.isDeactivated) return
159160
let { average } = this
160161
average *= this.heights.size
161162
let changed = false
@@ -212,8 +213,7 @@ export default {
212213
const count = Math.round(
213214
this.renderViewports * Math.ceil(window.innerHeight / this.average),
214215
)
215-
const prevStart = this.start
216-
const prevEnd = this.end
216+
const { start: prevStart, end: prevEnd } = this
217217
this.start = Math.max(index, 0)
218218
this.end = Math.min(this.start + count, this.itemsData.length)
219219
if (prevStart === this.start && prevEnd === this.end) return
@@ -302,5 +302,13 @@ export default {
302302
beforeDestroy() {
303303
this.observer.disconnect()
304304
},
305+
306+
activated() {
307+
this.isDeactivated = false
308+
},
309+
310+
deactivated() {
311+
this.isDeactivated = true
312+
},
305313
}
306314
</script>

src/mixins.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,24 @@ const throttled = function (handler, timeout) {
1515

1616
export const event = (event, { target, throttle } = {}) => {
1717
const funcName = `_${event}Handler`
18+
const deactivatedName = `_${event}Deactivated`
1819
if (!target) target = window
1920
return {
2021
mounted() {
21-
const handler = throttled(this[event + 'Handler'], throttle)
22-
this[funcName] = handler
23-
target.addEventListener(event, handler)
22+
this[funcName] = throttled(this[event + 'Handler'], throttle)
23+
target.addEventListener(event, this[funcName])
2424
},
2525
destroyed() {
26-
const handler = this[funcName]
27-
target.removeEventListener(event, handler)
26+
target.removeEventListener(event, this[funcName])
27+
},
28+
activated() {
29+
if (!this[deactivatedName]) return
30+
target.addEventListener(event, this[funcName])
31+
this[deactivatedName] = false
32+
},
33+
deactivated() {
34+
target.removeEventListener(event, this[funcName])
35+
this[deactivatedName] = true
2836
},
2937
}
3038
}

tests/__snapshots__/listscroller.test.js.snap

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,46 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`ListScroller component inside keep-alive ignores resize observer while deactivated 1`] = `
4+
<div
5+
style="height: 0px; position: relative; overflow: hidden;"
6+
>
7+
<div
8+
style="transform: translateY(0px);"
9+
>
10+
<div
11+
data-item-index="0"
12+
>
13+
0 0
14+
</div>
15+
<div
16+
data-item-index="1"
17+
>
18+
1 1
19+
</div>
20+
<div
21+
data-item-index="2"
22+
>
23+
2 2
24+
</div>
25+
<div
26+
data-item-index="3"
27+
>
28+
3 3
29+
</div>
30+
<div
31+
data-item-index="4"
32+
>
33+
4 4
34+
</div>
35+
<div
36+
data-item-index="5"
37+
>
38+
5 5
39+
</div>
40+
</div>
41+
</div>
42+
`;
43+
344
exports[`ListScroller component with 1000 items corrects spacer margin on scrolling up 1`] = `
445
<div
546
style="height: 20000px; position: relative; overflow: hidden;"
@@ -254,7 +295,7 @@ exports[`ListScroller component with 1000 items renders first items according to
254295
</div>
255296
`;
256297

257-
exports[`ListScroller component with 1000 items updates if itemesData changed 1`] = `
298+
exports[`ListScroller component with 1000 items updates if itemsData changed 1`] = `
258299
<div
259300
style="height: 2000px; position: relative; overflow: hidden;"
260301
>

tests/listscroller.test.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Item from './item'
44
import ResizeObserver from './resizeobserver'
55
jest.mock('./resizeobserver')
66
import { cloneDeep } from 'lodash'
7+
import Vue from 'vue'
78

89
const updateSizes = (expectedItems, clear = true) => {
910
expect(ResizeObserver).toBeCalledTimes(1)
@@ -362,7 +363,7 @@ describe('ListScroller component', () => {
362363
expect(wrapper.emitted('bottom').length).toBe(1)
363364
})
364365

365-
it('updates if itemesData changed', async () => {
366+
it('updates if itemsData changed', async () => {
366367
wrapper.setProps({ itemsData: itemsData.slice(0, 100) })
367368
jest.runAllTimers()
368369
updateSizes(12)
@@ -425,6 +426,62 @@ describe('ListScroller component', () => {
425426
})
426427
})
427428

429+
describe('inside keep-alive', () => {
430+
let wrapper
431+
beforeEach(() => {
432+
height = 30
433+
const keepAlive = Vue.component('test', {
434+
components: { ScrollerMock },
435+
template: `
436+
<keep-alive>
437+
<ScrollerMock v-if="show" :itemHeight="40" :itemsData="data" :itemComponent="item" />
438+
</keep-alive>
439+
`,
440+
data() {
441+
return { item: Item, data: itemsData }
442+
},
443+
props: { show: { type: Boolean, default: true } },
444+
})
445+
wrapper = mount(keepAlive)
446+
})
447+
448+
it('removes event listeners while deactivated', async () => {
449+
expect(window.addEventListener).toBeCalledTimes(2)
450+
const scroll = window.addEventListener.mock.calls[0][1]
451+
const resize = window.addEventListener.mock.calls[1][1]
452+
expect(window.addEventListener).toBeCalledWith('scroll', scroll)
453+
expect(window.addEventListener).toBeCalledWith('resize', resize)
454+
455+
// deactivating
456+
wrapper.setProps({ show: false })
457+
await wrapper.vm.$nextTick()
458+
expect(window.removeEventListener).toBeCalledTimes(2)
459+
expect(window.removeEventListener).toBeCalledWith('scroll', scroll)
460+
expect(window.removeEventListener).toBeCalledWith('resize', resize)
461+
462+
// activating
463+
window.addEventListener.mockClear()
464+
wrapper.setProps({ show: true })
465+
await wrapper.vm.$nextTick()
466+
expect(window.addEventListener).toBeCalledTimes(2)
467+
expect(window.addEventListener).toBeCalledWith('scroll', scroll)
468+
expect(window.addEventListener).toBeCalledWith('resize', resize)
469+
})
470+
471+
it('ignores resize observer while deactivated', async () => {
472+
wrapper.setProps({ show: false })
473+
await wrapper.vm.$nextTick()
474+
475+
height = 10
476+
updateSizes(6)
477+
await wrapper.vm.$nextTick()
478+
479+
wrapper.setProps({ show: true })
480+
await wrapper.vm.$nextTick()
481+
expect(wrapper.element).toMatchSnapshot()
482+
})
483+
})
484+
428485
it('gets item height from dom', () => {
429486
const wrapper = mount(ListScroller, {
430487
propsData: {

0 commit comments

Comments
 (0)