Skip to content

Commit 5097690

Browse files
jevin98sleeprite
authored andcommitted
!464 fix(splitPanel): splitPanelItem无法设置style/class与splitPanel可渲染非splitPanelItem组件
* fix(splitPanel): splitPanelItem无法设置style/class与splitPanel可渲染非splitPanelItem组件
1 parent 5787faf commit 5097690

File tree

7 files changed

+230
-214
lines changed

7 files changed

+230
-214
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { withInstall } from "../../utils";
2-
import Component from "./index.vue";
2+
import Component from "./splitPanel";
33

44
const component = withInstall(Component);
55
export default component;

packages/component/component/splitPanel/index.vue

Lines changed: 0 additions & 160 deletions
This file was deleted.

packages/component/component/splitPanel/interface.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { ComputedRef, Ref, ShallowRef } from "vue";
2-
1+
import type { ComputedRef, Ref, ShallowRef, InjectionKey } from "vue";
32
export interface StepProps {
43
vertical?: boolean;
54
minSize?: number;
@@ -15,6 +14,7 @@ export interface SplitPanelStepsType {
1514
export interface SplitPanelContext {
1615
props: Required<StepProps>;
1716
steps: Ref<SplitPanelStepsType[]>;
18-
target: Ref<HTMLDivElement | null>;
19-
moveChange: (event: MouseEvent, status: boolean, isVertical: boolean) => void;
2017
}
18+
19+
export const SPLITPANEL_INJECTION_KEY: InjectionKey<SplitPanelContext> =
20+
Symbol("LaySplitPanel");

packages/component/component/splitPanel/splitPanel.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import {
2+
type Component,
3+
type PropType,
4+
type Ref,
5+
ref,
6+
watch,
7+
provide,
8+
defineComponent,
9+
} from "vue";
10+
import "./index.less";
11+
12+
import {
13+
type StepProps,
14+
type SplitPanelStepsType,
15+
SPLITPANEL_INJECTION_KEY,
16+
} from "./interface";
17+
18+
import { flattedVNode } from "../../utils";
19+
20+
export default defineComponent({
21+
name: "LaySplitPanel",
22+
props: {
23+
vertical: {
24+
type: Boolean as PropType<StepProps["vertical"]>,
25+
default: () => false,
26+
},
27+
minSize: {
28+
type: Number as PropType<StepProps["minSize"]>,
29+
default: 50,
30+
},
31+
},
32+
setup(props, { slots }) {
33+
// line el width
34+
const LINE_WIDTH = 3;
35+
36+
const target = ref();
37+
38+
const domEvent = ref();
39+
const domStatus = ref();
40+
41+
const handleMousemove = (event: MouseEvent) => {
42+
const { left: boxLeft, top: boxTop } =
43+
target.value.getBoundingClientRect();
44+
45+
if (window.getSelection != undefined) {
46+
window.getSelection()?.removeAllRanges();
47+
}
48+
if (domStatus.value && domEvent.value) {
49+
if (!props.vertical) {
50+
baseSetStyleFlexBasis(
51+
event.clientX - boxLeft,
52+
domEvent.value.target.previousElementSibling.offsetLeft,
53+
domEvent.value.target.previousElementSibling.offsetWidth,
54+
domEvent.value.target.nextElementSibling.offsetWidth,
55+
target.value.offsetWidth
56+
);
57+
} else {
58+
baseSetStyleFlexBasis(
59+
event.clientY - boxTop,
60+
domEvent.value.target.previousElementSibling.offsetTop,
61+
domEvent.value.target.previousElementSibling.offsetHeight,
62+
domEvent.value.target.nextElementSibling.offsetHeight,
63+
target.value.offsetHeight
64+
);
65+
}
66+
}
67+
};
68+
69+
const baseSetStyleFlexBasis = (
70+
currentPoin: number, // 鼠标在当前splitPanel中 offsetLeft | offsetTop
71+
preDomOffset: number, // 上一个item offsetLeft | offsetTop
72+
preDomSize: number, // 上一个item offsetWidth | offsetHeight
73+
nextDomSize: number, // 下一个item offsetWidth | offsetHeight
74+
boxSize: number // splitPanel容器 offsetWidth | offsetHeight
75+
) => {
76+
const prevDom = domEvent.value.target.previousElementSibling;
77+
const nextDom = domEvent.value.target.nextElementSibling;
78+
79+
const otherSize = boxSize - (preDomSize + nextDomSize + LINE_WIDTH);
80+
const otherSizePercentage =
81+
((preDomSize + nextDomSize + LINE_WIDTH) / boxSize) * 100;
82+
83+
if (
84+
currentPoin - preDomOffset < props.minSize! ||
85+
boxSize - (currentPoin - preDomOffset) - otherSize < props.minSize!
86+
) {
87+
return false;
88+
}
89+
90+
prevDom.style.flexBasis =
91+
((currentPoin - preDomOffset) /
92+
(preDomSize + nextDomSize + LINE_WIDTH)) *
93+
otherSizePercentage +
94+
"%";
95+
96+
nextDom.style.flexBasis =
97+
((boxSize - (currentPoin - preDomOffset) - otherSize) /
98+
(preDomSize + nextDomSize + LINE_WIDTH)) *
99+
otherSizePercentage +
100+
"%";
101+
};
102+
103+
const moveChange = (event: MouseEvent) => {
104+
domEvent.value = event;
105+
domStatus.value = true;
106+
target.value.addEventListener("mousemove", handleMousemove);
107+
};
108+
109+
const mouseup = () => {
110+
domEvent.value = null;
111+
domStatus.value = false;
112+
target.value.removeEventListener("mousemove", handleMousemove);
113+
};
114+
115+
// 定义初始化个数数组
116+
const steps = ref<SplitPanelStepsType[]>([]);
117+
118+
// 监听有几个lay-split-panel-item
119+
watch(
120+
() => steps.value,
121+
(newVal) => {
122+
// 所有设置了space props的总数
123+
const spaces = newVal
124+
.filter((step) => step.space)
125+
.map((step) => step.space);
126+
127+
const spaceLength = spaces.join(" - ") || "0px";
128+
const other = newVal.length - spaces.length;
129+
130+
newVal.forEach((step, index) => {
131+
step.setIndex(index);
132+
133+
if (step.space) {
134+
step.itemEl!.style.flexBasis = `calc(${step.space} - ${LINE_WIDTH}px)`;
135+
} else {
136+
// 没有设置space 计算逻辑
137+
// ((总宽度 - 总spaces) / 没有设置space数量) = 剩下位置平分
138+
step.itemEl!.style.flexBasis = `calc(((100% - ${spaceLength}) / ${other}) - ${LINE_WIDTH}px)`;
139+
}
140+
});
141+
},
142+
{ flush: "post", deep: true }
143+
);
144+
145+
// 向lay-split-panel-item传递参数
146+
provide(SPLITPANEL_INJECTION_KEY, {
147+
props: props as Required<StepProps>,
148+
steps: steps as unknown as Ref<SplitPanelStepsType[]>,
149+
});
150+
151+
return () => {
152+
const itemSlots = !slots.default
153+
? []
154+
: flattedVNode(slots.default())
155+
?.filter((slot) => {
156+
return (slot.type as Component)?.name === "LaySplitPanelItem";
157+
})
158+
.map((slot, index) => {
159+
if (index) {
160+
return [
161+
<div
162+
class="lay-split-panel-line"
163+
onMousedown={moveChange}
164+
></div>,
165+
slot,
166+
];
167+
} else {
168+
return slot;
169+
}
170+
})
171+
.flat() || [];
172+
173+
return (
174+
<div
175+
ref={target}
176+
class={[
177+
"lay-split-panel",
178+
`lay-split-panel-${props.vertical ? "vertical" : "horizontal"}`,
179+
]}
180+
style={{
181+
cursor: domStatus.value
182+
? !props.vertical
183+
? "col-resize"
184+
: "row-resize"
185+
: "",
186+
}}
187+
onMouseup={mouseup}
188+
>
189+
{itemSlots}
190+
</div>
191+
);
192+
};
193+
},
194+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy