From 0d78ce755aded5635fdb1dd0d2387fe25ef9a3d5 Mon Sep 17 00:00:00 2001 From: litleSnow Date: Tue, 11 Mar 2025 17:14:56 +0800 Subject: [PATCH 1/4] feat(split): Added Delay Rendering --- src/split/demos/enUS/index.demo-entry.md | 2 + src/split/demos/enUS/lazy.demo.vue | 53 +++++++++++++++++++ src/split/demos/zhCN/index.demo-entry.md | 2 + src/split/demos/zhCN/lazy.demo.vue | 42 +++++++++++++++ src/split/src/Split.tsx | 67 ++++++++++++++++++++---- 5 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 src/split/demos/enUS/lazy.demo.vue create mode 100644 src/split/demos/zhCN/lazy.demo.vue diff --git a/src/split/demos/enUS/index.demo-entry.md b/src/split/demos/enUS/index.demo-entry.md index 366e57f4f79..c65d208317f 100644 --- a/src/split/demos/enUS/index.demo-entry.md +++ b/src/split/demos/enUS/index.demo-entry.md @@ -13,6 +13,7 @@ nest.vue event.vue slot.vue controlled.vue +lazy.vue ``` ## API @@ -32,6 +33,7 @@ controlled.vue | pane2-style | `Object \| string` | `undefined` | The Style of the second pane | 2.38.2 | | resize-trigger-size | `number` | `3` | Size of the resize trigger. | 2.36.0 | | size | `string \| number` | `undefined` | Split is the controlled split size, when it's `number` it should in 0 ~ 1, when it's `string` it should be formatted in `${number}px`. | 2.38.0, `string` 2.38.2 | +| lazy | `boolean` | `false` | Delay rendering | NEXT_VERSION | | watch-props | `Array<'defaultSize'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. | 2.38.0 | | on-drag-start | `(e: Event) => void` | `undefined` | Callback function when drag start. | 2.36.0 | | on-drag-move | `(e: Event) => void` | `undefined` | Callback function when dragging. | 2.36.0 | diff --git a/src/split/demos/enUS/lazy.demo.vue b/src/split/demos/enUS/lazy.demo.vue new file mode 100644 index 00000000000..926addbc28a --- /dev/null +++ b/src/split/demos/enUS/lazy.demo.vue @@ -0,0 +1,53 @@ + +# Delay rendering mode +When you have too much content, dragging and dropping frequently triggers element text re-arrangement/style re-painting, it will be very stuttering and affecting the user experience. +It can be optimized by delayed rendering and not updated until the drag and drop is finished. +Turn on delayed rendering by setting `lazy` to `true`. + + + + + diff --git a/src/split/demos/zhCN/index.demo-entry.md b/src/split/demos/zhCN/index.demo-entry.md index b416227edee..9ab03b260cd 100644 --- a/src/split/demos/zhCN/index.demo-entry.md +++ b/src/split/demos/zhCN/index.demo-entry.md @@ -14,6 +14,7 @@ event.vue slot.vue controlled.vue pixel-value.vue +lazy.vue ``` ## API @@ -33,6 +34,7 @@ pixel-value.vue | pane2-style | `Object \| string` | `undefined` | 第二个面板的样式 | 2.38.2 | | resize-trigger-size | `number` | `3` | Split 的分隔条大小 | 2.36.0 | | size | `string \| number` | `undefined` | Split 的受控分割大小,为 `number` 类型时应该为 0 ~ 1 之间的值,为 `string` 类型时应该为 `${number}px` 格式 | 2.38.0, `string` 2.38.2 | +| lazy | `boolean` | `false` | 延迟渲染 | NEXT_VERSION | | watch-props | `Array<'defaultSize'>` | `undefined` | 需要检测变更的默认属性,检测后组件状态会更新。注意:`watch-props` 本身不是响应式的 | 2.38.0 | | on-drag-start | `(e: Event) => void` | `undefined` | 开始拖拽的回调函数 | 2.36.0 | | on-drag-move | `(e: Event) => void` | `undefined` | 拖拽中的回调函数 | 2.36.0 | diff --git a/src/split/demos/zhCN/lazy.demo.vue b/src/split/demos/zhCN/lazy.demo.vue new file mode 100644 index 00000000000..1f4bf22cf66 --- /dev/null +++ b/src/split/demos/zhCN/lazy.demo.vue @@ -0,0 +1,42 @@ + +# 延迟渲染模式 +当你内容太多的时候, 拖拽频繁触发元素文字重排 / 样式重绘时, 会很卡顿,影响用户体验。 +可以通过延迟渲染进行优化,直到拖拽结束才更新。 +通过设置 `lazy` 为 `true` 来开启延迟渲染。 + + + + + diff --git a/src/split/src/Split.tsx b/src/split/src/Split.tsx index 153a0013d51..20f6015d433 100644 --- a/src/split/src/Split.tsx +++ b/src/split/src/Split.tsx @@ -41,6 +41,10 @@ export const splitProps = { onUpdateSize: [Function, Array] as PropType< SplitOnUpdateSize | SplitOnUpdateSize[] >, + lazy: { + type: Boolean as PropType, + default: false + }, size: [String, Number] as PropType, min: { type: [String, Number] as PropType, @@ -102,7 +106,7 @@ export default defineComponent({ if (props.watchProps?.includes('defaultSize')) { watchEffect(() => (uncontrolledSizeRef.value = props.defaultSize)) } - // use to update controlled or uncontrolled values + // 更新受控或非受控的大小值 const doUpdateSize = (size: number | string): void => { const _onUpdateSize = props['onUpdate:size'] if (props.onUpdateSize) @@ -112,6 +116,10 @@ export default defineComponent({ uncontrolledSizeRef.value = size } const mergedSizeRef = useMergedState(controlledSizeRef, uncontrolledSizeRef) + // 当 lazy 为 true 时,拖拽过程中先将新的大小保存到 pendingSizeRef + const pendingSizeRef = ref(mergedSizeRef.value) + // 用于实时显示拖拽指示线的样式 + const indicatorStyle = ref({}) const firstPaneStyle = computed(() => { const sizeValue = mergedSizeRef.value @@ -164,7 +172,12 @@ export default defineComponent({ if (props.onDragMove) props.onDragMove(e) } - const onMouseUp = (): void => { + const onMouseUp = (e: MouseEvent): void => { + // lazy 模式下拖拽结束时更新大小,并清空指示线 + if (props.lazy) { + doUpdateSize(pendingSizeRef.value) + indicatorStyle.value = {} + } off(mouseMoveEvent, document, onMouseMove) off(mouseUpEvent, document, onMouseUp) isDraggingRef.value = false @@ -211,7 +224,6 @@ export default defineComponent({ : event.clientY - containerRect.top + offset const { min, max } = props - const pxMin = typeof min === 'string' ? depx(min) : min * containerUsableSize const pxMax @@ -220,13 +232,41 @@ export default defineComponent({ let nextPxSize = newPxSize nextPxSize = Math.max(nextPxSize, pxMin) nextPxSize = Math.min(nextPxSize, pxMax, containerUsableSize) - // in pixel mode + + let newSize: number | string if (typeof mergedSizeRef.value === 'string') { - doUpdateSize(`${nextPxSize}px`) + newSize = `${nextPxSize}px` + } + else { + newSize = nextPxSize / containerUsableSize + } + // 根据 lazy 判断是否立即更新 + if (props.lazy) { + pendingSizeRef.value = newSize + // 更新指示线样式,指示线跟随鼠标移动 + if (direction === 'horizontal') { + indicatorStyle.value = { + position: 'absolute', + left: `${nextPxSize}px`, + top: '0', + bottom: '0', + width: '1px', + background: cssVarsRef.value['--n-resize-trigger-color-hover'] + } + } + else { + indicatorStyle.value = { + position: 'absolute', + top: `${nextPxSize}px`, + left: '0', + right: '0', + height: '1px', + background: cssVarsRef.value['--n-resize-trigger-color-hover'] + } + } } else { - // in percentage mode - doUpdateSize(nextPxSize / containerUsableSize) + doUpdateSize(newSize) } } @@ -244,7 +284,9 @@ export default defineComponent({ resizeTriggerWrapperStyle, resizeTriggerStyle, handleMouseDown, - firstPaneStyle + firstPaneStyle, + indicatorStyle, + lazy: props.lazy } }, render() { @@ -256,7 +298,7 @@ export default defineComponent({ `${this.mergedClsPrefix}-split--${this.direction}`, this.themeClass ]} - style={this.cssVars as CSSProperties} + style={[this.cssVars as CSSProperties, { position: 'relative' }]} >
)} + {this.lazy && this.isDragging && ( +
+
+ )}
Date: Tue, 11 Mar 2025 17:19:26 +0800 Subject: [PATCH 2/4] feat(Split): update changelog --- CHANGELOG.en-US.md | 4 ++++ CHANGELOG.zh-CN.md | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index ba3d5ba01e6..090aacf7463 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -1,5 +1,9 @@ # CHANGELOG +### Feature + +- 为 Split组件添加了 lazy 延迟渲染属性 + ## 2.41.0 `2025-01-05` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index aee800ad1d2..c36d54e4cbb 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -1,5 +1,11 @@ # CHANGELOG +## NEXT_VERSION + +### Feature + +- 为 Split组件添加了 lazy 延迟渲染属性 + ## 2.41.0 `2025-01-05` From caf4a60f97d283c356c6f1b64648a51ba4e59c2a Mon Sep 17 00:00:00 2001 From: litleSnow Date: Tue, 11 Mar 2025 17:19:49 +0800 Subject: [PATCH 3/4] feat(Split): update changelog --- CHANGELOG.en-US.md | 2 +- CHANGELOG.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 090aacf7463..2adaa0ef1a4 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -1,6 +1,6 @@ # CHANGELOG -### Feature +### Features - 为 Split组件添加了 lazy 延迟渲染属性 diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index c36d54e4cbb..1dff7adefca 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -2,7 +2,7 @@ ## NEXT_VERSION -### Feature +### Features - 为 Split组件添加了 lazy 延迟渲染属性 From 897be5239f0d6a01cf5f26e7c39ec54fa1f21447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiaxin=C2=B7Li?= <97370135+XueHua-s@users.noreply.github.com> Date: Tue, 11 Mar 2025 18:52:45 +0800 Subject: [PATCH 4/4] fix: change Code Comments language from Chinese into English --- src/split/src/Split.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/split/src/Split.tsx b/src/split/src/Split.tsx index 20f6015d433..35986ecf476 100644 --- a/src/split/src/Split.tsx +++ b/src/split/src/Split.tsx @@ -106,7 +106,7 @@ export default defineComponent({ if (props.watchProps?.includes('defaultSize')) { watchEffect(() => (uncontrolledSizeRef.value = props.defaultSize)) } - // 更新受控或非受控的大小值 + // Update controlled or uncontrolled size values const doUpdateSize = (size: number | string): void => { const _onUpdateSize = props['onUpdate:size'] if (props.onUpdateSize) @@ -116,9 +116,9 @@ export default defineComponent({ uncontrolledSizeRef.value = size } const mergedSizeRef = useMergedState(controlledSizeRef, uncontrolledSizeRef) - // 当 lazy 为 true 时,拖拽过程中先将新的大小保存到 pendingSizeRef + // When lazy is true, save the new size to pendingSizeRef during dragging const pendingSizeRef = ref(mergedSizeRef.value) - // 用于实时显示拖拽指示线的样式 + // Styles for real-time display of drag and drop indicator lines const indicatorStyle = ref({}) const firstPaneStyle = computed(() => { @@ -173,7 +173,7 @@ export default defineComponent({ props.onDragMove(e) } const onMouseUp = (e: MouseEvent): void => { - // lazy 模式下拖拽结束时更新大小,并清空指示线 + // Update the size at the end of dragging in lazy mode and clear the indicator line if (props.lazy) { doUpdateSize(pendingSizeRef.value) indicatorStyle.value = {} @@ -240,10 +240,10 @@ export default defineComponent({ else { newSize = nextPxSize / containerUsableSize } - // 根据 lazy 判断是否立即更新 + // Judging from lazy whether to update immediately if (props.lazy) { pendingSizeRef.value = newSize - // 更新指示线样式,指示线跟随鼠标移动 + // Update the indicator line style, the indicator line follows the mouse if (direction === 'horizontal') { indicatorStyle.value = { position: 'absolute',