use rIC in pseudo virtual list
This commit is contained in:
parent
03b055ab20
commit
d1620c3bca
|
@ -7244,6 +7244,11 @@
|
|||
"setimmediate": "1.0.5"
|
||||
}
|
||||
},
|
||||
"tiny-queue": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz",
|
||||
"integrity": "sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.31",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"svelte-loader": "^2.3.3",
|
||||
"svelte-transitions": "^1.1.1",
|
||||
"svgo": "^1.0.3",
|
||||
"tiny-queue": "^0.2.1",
|
||||
"uglifyjs-webpack-plugin": "^1.1.5",
|
||||
"url-search-params": "^0.10.0",
|
||||
"webpack": "^3.10.0",
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
makeProps="{{makeProps}}"
|
||||
key="{{wrappedItem.item}}"
|
||||
intersectionObserver="{{intersectionObserver}}"
|
||||
hide="{{shouldHide(wrappedItem.item, $intersectionStates)}}"
|
||||
isIntersecting="{{isIntersecting(wrappedItem.item, $intersectionStates)}}"
|
||||
isCached="{{isCached(wrappedItem.item, $intersectionStates)}}"
|
||||
height="{{getHeight(wrappedItem.item, $intersectionStates)}}"
|
||||
/>
|
||||
{{/each}}
|
||||
|
@ -35,7 +36,7 @@
|
|||
let intersectionStates = this.store.get('intersectionStates')
|
||||
let keys = Object.keys(intersectionStates)
|
||||
for (let key of keys) {
|
||||
intersectionStates[key].isIntersecting = false
|
||||
intersectionStates[key].isCached = true
|
||||
}
|
||||
this.store.setForRealm({intersectionStates: intersectionStates})
|
||||
|
||||
|
@ -60,8 +61,11 @@
|
|||
}
|
||||
},
|
||||
helpers: {
|
||||
shouldHide(key, $intersectionStates) {
|
||||
return !!($intersectionStates[key] && !$intersectionStates[key].isIntersecting)
|
||||
isIntersecting(key, $intersectionStates) {
|
||||
return !!($intersectionStates[key] && $intersectionStates[key].isIntersecting)
|
||||
},
|
||||
isCached(key, $intersectionStates) {
|
||||
return !!($intersectionStates[key] && $intersectionStates[key].isCached)
|
||||
},
|
||||
getHeight(key, $intersectionStates) {
|
||||
return $intersectionStates[key] && $intersectionStates[key].rect.height
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="pseudo-virtual-list-item"
|
||||
aria-hidden="{{hide}}"
|
||||
pseudo-virtual-list-key="{{key}}"
|
||||
style="height: {{hide ? `${height}px` : ''}};"
|
||||
style="height: {{shouldHide ? `${height}px` : ''}};"
|
||||
ref:node>
|
||||
{{#if !hide}}
|
||||
{{#if !shouldHide}}
|
||||
<:Component {component}
|
||||
virtualProps="{{props}}"
|
||||
virtualIndex="{{index}}"
|
||||
|
@ -13,10 +13,38 @@
|
|||
</div>
|
||||
<script>
|
||||
|
||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||
import { mark, stop } from '../../_utils/marks'
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
this.observe('isIntersecting', isIntersecting => {
|
||||
if (isIntersecting) {
|
||||
mark('render')
|
||||
this.set({hide: false})
|
||||
stop('render')
|
||||
} else {
|
||||
// unrender lazily; it's not a critical UI task
|
||||
scheduleIdleTask(() => {
|
||||
mark('unrender')
|
||||
if (!this.get('isIntersecting')) {
|
||||
this.set({hide: true})
|
||||
}
|
||||
stop('unrender')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let intersectionObserver = this.get('intersectionObserver')
|
||||
intersectionObserver.observe(this.refs.node)
|
||||
},
|
||||
computed: {
|
||||
shouldHide: (isIntersecting, isCached, hide) => {
|
||||
if (isCached) {
|
||||
return true // if it's cached, always unrender immediately until proven it's intersecting
|
||||
}
|
||||
return !isIntersecting && hide
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
:index
|
||||
:scrollToThisItem
|
||||
:intersectionObserver
|
||||
:hide
|
||||
:isIntersecting
|
||||
:isCached
|
||||
:height
|
||||
on:scrollToPosition
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Wrapper to call requestIdleCallback() to schedule low-priority work.
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API
|
||||
// for a good breakdown of the concepts behind this.
|
||||
|
||||
import Queue from 'tiny-queue'
|
||||
|
||||
const taskQueue = new Queue()
|
||||
let runningRequestIdleCallback = false
|
||||
|
||||
function runTasks(deadline) {
|
||||
while (taskQueue.length && deadline.timeRemaining() > 0) {
|
||||
taskQueue.shift()()
|
||||
}
|
||||
if (taskQueue.length) {
|
||||
requestIdleCallback(runTasks)
|
||||
} else {
|
||||
runningRequestIdleCallback = false
|
||||
}
|
||||
}
|
||||
|
||||
export function scheduleIdleTask(task) {
|
||||
taskQueue.push(task)
|
||||
if (!runningRequestIdleCallback) {
|
||||
runningRequestIdleCallback = true
|
||||
requestIdleCallback(runTasks)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue