perf(select): use v-show to trigger open fast

This commit is contained in:
07akioni 2021-05-17 13:42:55 +08:00
parent a1849ec814
commit 96020751fd
7 changed files with 92 additions and 54 deletions

View File

@ -2,7 +2,12 @@
## Pending
## Feats
### Perf
- Optimize `n-data-table` init render count.
- Optimize `n-select` open duration after first opening.
### Feats
- `n-tree` add `virtual-scroll` prop.
- `n-data-table` add `virtual-scroll` prop.

View File

@ -2,7 +2,12 @@
## Pending
## Feats
### Perf
- 优化 `n-data-table` 初始渲染次数
- 优化 `n-select` 首次打开后打开用时
### Feats
- `n-tree` 新增 `virtual-scroll` 属性
- `n-data-table` 新增 `virtual-scroll` 属性

View File

@ -4,30 +4,30 @@ module.exports = {
presets:
process.env.NODE_ENV === 'test'
? [
['@babel/preset-env', { targets: { node: 'current' } }],
[
'@babel/preset-typescript',
{
allExtensions: true,
isTSX: true,
jsxPragma: 'h',
jsxPragmaFrag: 'Fragment'
}
],
[
'@babel/preset-react',
{
pragma: 'h',
pragmaFrag: 'Fragment'
}
['@babel/preset-env', { targets: { node: 'current' } }],
[
'@babel/preset-typescript',
{
allExtensions: true,
isTSX: true,
jsxPragma: 'h',
jsxPragmaFrag: 'Fragment'
}
],
[
'@babel/preset-react',
{
pragma: 'h',
pragmaFrag: 'Fragment'
}
]
]
]
: [
[
'@babel/preset-env',
{
targets: '>2%, not IE 11'
}
[
'@babel/preset-env',
{
targets: '>2%, not IE 11'
}
]
]
]
}

View File

@ -100,6 +100,11 @@ export default defineComponent({
type: Boolean,
default: true
},
// show is used to toggle pending state initialization
show: {
type: Boolean,
default: true
},
loading: Boolean,
focusable: Boolean,
onMousedown: Function as PropType<(e: MouseEvent) => void>,
@ -128,22 +133,29 @@ export default defineComponent({
const fIndexGetterRef = computed(() =>
createIndexGetter(flattenedNodesRef.value)
)
const { treeMate } = props
const pendingNodeRef = ref(
props.autoPending
? props.value === null
? treeMate.getFirstAvailableNode()
: props.multiple
? treeMate.getNode(
((props.value as Array<string | number> | null) || [])[
((props.value as Array<string | number> | null) || []).length -
1
]
) || treeMate.getFirstAvailableNode()
: treeMate.getNode(props.value as string | number) ||
treeMate.getFirstAvailableNode()
: null
)
const pendingNodeRef = ref<TreeNode<SelectBaseOption> | null>(null)
function initPendingNode (): void {
const { treeMate } = props
setPendingTmNode(
props.autoPending
? props.value === null
? treeMate.getFirstAvailableNode()
: props.multiple
? treeMate.getNode(
((props.value as Array<string | number> | null) || [])[
((props.value as Array<string | number> | null) || [])
.length - 1
]
) || treeMate.getFirstAvailableNode()
: treeMate.getNode(props.value as string | number) ||
treeMate.getFirstAvailableNode()
: null
)
}
watch(toRef(props, 'show'), (value) => {
if (value) initPendingNode()
})
initPendingNode()
const defaultScrollIndex = pendingNodeRef.value
? fIndexGetterRef.value(pendingNodeRef.value.key) ?? undefined
: undefined

View File

@ -10,16 +10,18 @@
```
```js
export default {
data () {
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
value: null,
values: null,
value: ref(null),
values: ref(null),
options: Array.apply(null, { length: 42000 }).map((_, i) => ({
label: String(i),
value: i
}))
}
}
}
})
```

View File

@ -10,16 +10,18 @@
```
```js
export default {
data () {
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
value: null,
values: null,
value: ref(null),
values: ref(null),
options: Array.apply(null, { length: 42000 }).map((_, i) => ({
label: String(i),
value: i
}))
}
}
}
})
```

View File

@ -9,7 +9,8 @@ import {
ComputedRef,
watch,
Transition,
withDirectives
withDirectives,
vShow
} from 'vue'
import { createTreeMate } from 'treemate'
import { VBinder, VFollower, VTarget, FollowerRef } from 'vueuc'
@ -186,6 +187,10 @@ const selectProps = {
autofocus: {
type: Boolean,
default: false
},
displayDirective: {
type: String as PropType<'if' | 'show'>,
default: 'show'
}
} as const
@ -759,7 +764,8 @@ export default defineComponent({
>
{{
default: () =>
this.mergedShow &&
(this.mergedShow ||
this.displayDirective === 'show') &&
withDirectives(
<NInternalSelectMenu
ref="menuRef"
@ -785,10 +791,16 @@ export default defineComponent({
onKeydown={this.handleMenuKeydown}
onTabOut={this.handleMenuTabOut}
onMousedown={this.handleMenuMousedown}
show={this.mergedShow}
>
{$slots}
</NInternalSelectMenu>,
[[clickoutside, this.handleMenuClickOutside]]
this.displayDirective === 'show'
? [
[vShow, this.mergedShow],
[clickoutside, this.handleMenuClickOutside]
]
: [[clickoutside, this.handleMenuClickOutside]]
)
}}
</Transition>