Skip to content

Commit

Permalink
refactor: visible condition of modal component (#5078)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/area console
/kind improvement
/milestone 2.12.x

#### What this PR does / why we need it:

重构 UI 的 Modal 组件,支持通过 v-if 控制是否显示(渲染)。

example:

```vue
<script lang="ts" setup>
import { ref } from "vue"
const visible = ref(false)
const modal = ref()

function open() {
  visible.value = true
}

function close() {
  modal.value.close()
}
</script>

<template>
  <button @click="open">Open</button>
    <VModal v-if="visible" ref="modal" title="test">
      <button @click="close">Close</button>
    </VModal>
</template>
```

#### Which issue(s) this PR fixes:

Fixes #5077 

#### Special notes for your reviewer:

测试方式:

1. cd console && pnpm --filter "./packages/components" storybook
2. 测试 Modal 组件在文档中是否工作正常。
3. 启动 Console 或者 UC。
4. 观察以前页面上的弹框是否工作正常。

#### Does this PR introduce a user-facing change?

```release-note
重构 UI 的 Modal 组件,支持通过 v-if 控制是否显示(渲染)。
```
  • Loading branch information
ruibaby authored Dec 29, 2023
1 parent 36ebc24 commit 44cb311
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { VModal } from ".";
import { VButton } from "../button";
import { IconArrowLeft, IconArrowRight } from "@/icons/icons";
import { VSpace } from "../space";
import { ref } from "vue";

const meta: Meta<typeof VModal> = {
title: "Modal",
Expand All @@ -12,16 +13,20 @@ const meta: Meta<typeof VModal> = {
render: (args) => ({
components: { VModal, VButton, VSpace, IconArrowLeft, IconArrowRight },
setup() {
return { args };
const modal = ref();
return { args, modal };
},
template: `
<VButton type="secondary" @click="args.visible = true">打开</VButton>
<VModal
v-model:visible="args.visible"
ref="modal"
v-if="args.visible"
:fullscreen="args.fullscreen"
:title="args.title"
:width="args.width"
:mount-to-body="true"
:layerClosable="true"
@close="args.visible = false"
>
<template #actions>
<span>
Expand All @@ -43,7 +48,7 @@ const meta: Meta<typeof VModal> = {
<VButton loading type="primary" @click="args.visible = false"
>确定
</VButton>
<VButton @click="args.visible = false">取消</VButton>
<VButton @click="modal.close()">取消</VButton>
</VSpace>
</template>
</VModal>
Expand Down
49 changes: 31 additions & 18 deletions console/packages/components/src/components/modal/Modal.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { computed, nextTick, reactive, ref, watch } from "vue";
import { computed, nextTick, reactive, ref, watch, onMounted } from "vue";
import { IconClose } from "../../icons/icons";
import type { UseOverlayScrollbarsParams } from "overlayscrollbars-vue";
import { useOverlayScrollbars } from "overlayscrollbars-vue";
Expand All @@ -17,7 +17,7 @@ const props = withDefaults(
layerClosable?: boolean;
}>(),
{
visible: false,
visible: undefined,
title: undefined,
width: 500,
height: undefined,
Expand All @@ -34,9 +34,23 @@ const emit = defineEmits<{
(event: "close"): void;
}>();
const internalVisible = ref(false);
const rootVisible = ref(false);
const modelWrapper = ref<HTMLElement>();
watch(
() => props.visible,
() => {
internalVisible.value = props.visible;
}
);
onMounted(() => {
if (props.visible === undefined) {
internalVisible.value = true;
}
});
const wrapperClasses = computed(() => {
return {
"modal-wrapper-fullscreen": props.fullscreen,
Expand All @@ -52,10 +66,17 @@ const contentStyles = computed(() => {
});
function handleClose() {
emit("update:visible", false);
emit("close");
internalVisible.value = false;
setTimeout(() => {
emit("update:visible", false);
emit("close");
}, 200);
}
defineExpose({
close: handleClose,
});
const focus = ref(false);
function handleClickLayer() {
Expand All @@ -69,17 +90,6 @@ function handleClickLayer() {
}, 300);
}
watch(
() => props.visible,
() => {
if (props.visible) {
nextTick(() => {
modelWrapper.value?.focus();
});
}
}
);
// body scroll
const modalBody = ref(null);
const reactiveParams = reactive<UseOverlayScrollbarsParams>({
Expand All @@ -93,10 +103,13 @@ const reactiveParams = reactive<UseOverlayScrollbarsParams>({
});
const [initialize, instance] = useOverlayScrollbars(reactiveParams);
watch(
() => props.visible,
() => internalVisible.value,
(value) => {
if (value) {
if (modalBody.value) initialize({ target: modalBody.value });
nextTick(() => {
modelWrapper.value?.focus();
});
} else {
instance()?.destroy();
}
Expand Down Expand Up @@ -126,7 +139,7 @@ watch(
@after-leave="rootVisible = false"
>
<div
v-show="visible"
v-show="internalVisible"
class="modal-layer"
@click.stop="handleClickLayer()"
/>
Expand All @@ -140,7 +153,7 @@ watch(
leave-to-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div
v-show="visible"
v-show="internalVisible"
:style="contentStyles"
class="modal-content transform transition-all duration-300"
:class="{ 'modal-focus': focus }"
Expand Down

0 comments on commit 44cb311

Please sign in to comment.