From e0679f91db1fe7c8460dca06fc7b336d0d8b04fa Mon Sep 17 00:00:00 2001 From: zhuchenxi Date: Mon, 25 Oct 2021 10:22:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(splitter):=20=E4=BF=AE=E5=A4=8D=E5=88=86?= =?UTF-8?q?=E5=89=B2=E7=BA=BF=E6=A0=B7=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/splitter/src/splitter-pane.tsx | 114 ++++++++++++++++----------- devui/splitter/src/splitter.tsx | 30 +++---- 2 files changed, 82 insertions(+), 62 deletions(-) diff --git a/devui/splitter/src/splitter-pane.tsx b/devui/splitter/src/splitter-pane.tsx index b6f17388..55760c69 100644 --- a/devui/splitter/src/splitter-pane.tsx +++ b/devui/splitter/src/splitter-pane.tsx @@ -20,7 +20,38 @@ export default defineComponent({ setup(props: SplitterPaneProps, { slots, expose }) { const store: SplitterStore = inject('splitterStore'); const domRef = ref(); - const order = ref(); + const orderRef = ref(); + watch([orderRef, domRef], + ([order, ele]) => { + if (!ele) { + return; + } + setStyle(ele, { order }); + } + ); + + // pane 初始化大小 + const setSizeStyle = (curSize: string) => { + const ele = domRef.value; + if (!ele) { + return; + } + + ele.style.flexBasis = curSize; + const paneFixedClass = 'devui-splitter-pane-fixed'; + if (curSize) { + // 设置 flex-grow 和 flex-shrink + addClass(ele, paneFixedClass); + } else { + removeClass(ele, paneFixedClass); + } + }; + + watch( + () => props.size, + setSizeStyle, + { immediate: true } + ); const orientation = inject('orientation'); let initialSize = ''; // 记录初始化挂载传入的大小 @@ -35,70 +66,59 @@ export default defineComponent({ // 获取当前 pane大小 const getPaneSize = (): number => { - const el = domRef?.value; + const ele = domRef.value; + if (!ele) { + return; + } if (orientation === 'vertical') { - return el.offsetHeight; + return ele.offsetHeight; } else { - return el.offsetWidth; + return ele.offsetWidth; } }; - onMounted(() => { - watch([order, domRef], ([order, dom]) => { - if (!(dom instanceof HTMLElement)) { + watch( + () => props.collapsed, + (collapsed: boolean) => { + const ele = domRef.value; + if (!ele) { return; } - setStyle(dom, { order }); - }); - - watch(() => props.size, (curSize: string) => { - const ele = domRef.value; - ele.style.flexBasis = curSize; - const paneFixedClass = 'devui-splitter-pane-fixed'; - if (curSize) { - // 设置 flex-grow 和 flex-shrink - addClass(ele, paneFixedClass); + const paneHiddenClass = 'devui-splitter-pane-hidden'; + if (!collapsed) { + removeClass(ele, paneHiddenClass); } else { - removeClass(ele, paneFixedClass); + addClass(ele, paneHiddenClass); } - }, { immediate: true }); - - watch(() => props.collapsed, (collapsed: boolean) => { - const paneHiddenClass = 'devui-splitter-pane-hidden'; - nextTick(() => { - const el = domRef.value; - if (!collapsed) { - removeClass(el, paneHiddenClass); - } else { - addClass(el, paneHiddenClass); - } - if (collapsed && props.shrink) { - removeClass(el, paneHiddenClass); - setStyle(el, { flexBasis: `${props.shrinkWidth}px` }); - } else { - setStyle(el, { flexBasis: initialSize }); - } - }); - }, { immediate: true }); - }); + if (collapsed && props.shrink) { + removeClass(ele, paneHiddenClass); + setStyle(ele, { flexBasis: `${props.shrinkWidth}px` }); + } else { + setStyle(ele, { flexBasis: initialSize }); + } + }, + { immediate: true } + ); // 收起时用于改变相邻 pane 的 flex-grow 属性来改变非自适应 pane 的 size const toggleNearPaneFlexGrow = (collapsed: boolean) => { - nextTick(() => { - const flexGrowClass = 'devui-splitter-pane-grow'; - if (hasClass(domRef.value, flexGrowClass)) { - removeClass(domRef.value, flexGrowClass); - } else if (collapsed) { - addClass(domRef.value, flexGrowClass); - } - }); + const ele = domRef.value; + if (!(ele instanceof HTMLElement)) { + return; + } + const flexGrowClass = 'devui-splitter-pane-grow'; + if (hasClass(ele, flexGrowClass)) { + removeClass(ele, flexGrowClass); + } else if (collapsed) { + addClass(ele, flexGrowClass); + } }; // 暴露给外部使用 expose({ - order, + order: orderRef, getPaneSize, toggleNearPaneFlexGrow, }); diff --git a/devui/splitter/src/splitter.tsx b/devui/splitter/src/splitter.tsx index aa524e40..49abaf38 100644 --- a/devui/splitter/src/splitter.tsx +++ b/devui/splitter/src/splitter.tsx @@ -1,4 +1,4 @@ -import { defineComponent, reactive, ref, provide, nextTick, onMounted } from 'vue' +import { defineComponent, reactive, ref, provide, nextTick, watch } from 'vue' import { splitterProps, SplitterProps } from './splitter-types' import DSplitterBar from './splitter-bar' import { SplitterStore } from './splitter-store' @@ -20,22 +20,22 @@ export default defineComponent({ state.panes = ctx.slots.DSplitterPane?.() || [] store.setPanes({ panes: state.panes }) - - const domRef = ref() - provide('orientation', props.orientation) provide('splitterStore', store) - onMounted(() => { - nextTick(() => { - let containerSize = 0 - if (props.orientation === 'vertical') { - containerSize = domRef.value.clientHeight - } else { - containerSize = domRef.value.clientWidth - } - store.setSplitter({ containerSize }) - }) - }); + + const domRef = ref() + watch(domRef, (ele) => { + if (!ele) { + return; + } + let containerSize = 0 + if (props.orientation === 'vertical') { + containerSize = ele.clientHeight + } else { + containerSize = ele.clientWidth + } + store.setSplitter({ containerSize }) + }) return () => { const { splitBarSize, orientation, showCollapseButton } = props -- Gitee