perf: DrawerOverlay 使用 Model

This commit is contained in:
kuaifan 2022-05-15 22:46:32 +08:00
parent 6610a948c5
commit 6e8ee60df0
7 changed files with 261 additions and 265 deletions

View File

@ -62,7 +62,7 @@ export default {
}, },
computed: { computed: {
...mapState(['userId', 'userToken', 'cacheDrawerOverlay']), ...mapState(['userId', 'userToken']),
}, },
watch: { watch: {
@ -221,10 +221,6 @@ export default {
if (this.$Modal.removeLast()) { if (this.$Modal.removeLast()) {
return true; return true;
} }
if (this.cacheDrawerOverlay.length > 0) {
this.cacheDrawerOverlay[this.cacheDrawerOverlay.length - 1].close();
return true;
}
} }
this.$Electron.registerMsgListener('dispatch', args => { this.$Electron.registerMsgListener('dispatch', args => {
if (!$A.isJson(args)) { if (!$A.isJson(args)) {

View File

@ -1,177 +0,0 @@
<template>
<div
v-transfer-dom
:data-transfer="transfer"
:class="['drawer-overlay', placement, value ? 'overlay-visible' : 'overlay-hide']"
:style="overlayStyle">
<div class="overlay-mask" @click="mask"></div>
<div class="overlay-body" :style="bodyStyle">
<div class="overlay-close">
<a href="javascript:void(0)" @click.stop="close">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" fill="none" role="img" class="icon fill-current">
<path d="M8.28596 6.51819C7.7978 6.03003 7.00634 6.03003 6.51819 6.51819C6.03003 7.00634 6.03003 7.7978 6.51819 8.28596L11.2322 13L6.51819 17.714C6.03003 18.2022 6.03003 18.9937 6.51819 19.4818C7.00634 19.97 7.7978 19.97 8.28596 19.4818L13 14.7678L17.714 19.4818C18.2022 19.97 18.9937 19.97 19.4818 19.4818C19.97 18.9937 19.97 18.2022 19.4818 17.714L14.7678 13L19.4818 8.28596C19.97 7.7978 19.97 7.00634 19.4818 6.51819C18.9937 6.03003 18.2022 6.03003 17.714 6.51819L13 11.2322L8.28596 6.51819Z" fill="currentColor"></path>
</svg>
</a>
</div>
<ResizeLine v-if="resize" class="overlay-resize" :placement="placement" v-model="dynamicSize" :min="minSize" :max="0" reverse/>
<div class="overlay-content"><slot/></div>
</div>
</div>
</template>
<script>
import ResizeLine from "./ResizeLine";
import TransferDom from '../directives/transfer-dom';
import {mapState} from "vuex";
export default {
name: 'DrawerOverlay',
components: {ResizeLine},
directives: { TransferDom },
props: {
value: {
type: Boolean,
default: false
},
maskClosable: {
type: Boolean,
default: true
},
escClosable: {
type: Boolean,
default: true
},
placement: {
validator (value) {
return ['right', 'bottom'].includes(value)
},
default: 'bottom'
},
size: {
type: [Number, String],
default: "100%"
},
minSize: {
type: Number,
default: 300
},
resize: {
type: Boolean,
default: true
},
transfer: {
type: Boolean,
default: false
},
beforeClose: Function
},
data() {
return {
dynamicSize: 0,
zIndex: 0,
}
},
mounted () {
document.addEventListener('keydown', this.escClose);
},
beforeDestroy () {
document.removeEventListener('keydown', this.escClose);
},
computed: {
...mapState(['cacheDrawerIndex']),
overlayStyle() {
return {
zIndex: 1000 + this.zIndex
}
},
bodyStyle() {
let size = this.dynamicSize;
size = size <= 100 ? `${size}%` : `${size}px`
if (this.placement == 'right') {
return {
width: size,
height: "100%"
}
} else {
return {
width: "100%",
height: size,
}
}
}
},
watch: {
value(val) {
if (this._uid) {
const index = this.$store.state.cacheDrawerOverlay.findIndex(({_uid}) => _uid === this._uid);
if (val && index === -1) {
this.$store.state.cacheDrawerOverlay.push({
_uid: this._uid,
close: this.close
});
}
if (!val && index > -1) {
this.$store.state.cacheDrawerOverlay.splice(index, 1);
}
}
//
if (val) {
this.zIndex = this.$store.state.cacheDrawerIndex++;
} else if (this.$store.state.cacheDrawerOverlay.length === 0) {
this.$store.state.cacheDrawerIndex = 0;
}
},
size: {
handler(val) {
this.dynamicSize = parseInt(val);
},
immediate: true
}
},
methods: {
mask() {
if (this.maskClosable) {
this.close()
}
},
close() {
if (!this.beforeClose) {
return this.handleClose();
}
const before = this.beforeClose();
if (before && before.then) {
before.then(this.handleClose);
} else {
this.handleClose();
}
},
handleClose () {
this.$emit("input", false)
},
escClose(e) {
if (this.value && this.escClosable) {
if (e.keyCode === 27) {
if (this.$Modal.visibles().length > 0) {
return;
}
const list = this.$store.state.cacheDrawerOverlay;
if (list.length > 0) {
const $Drawer = list[list.length - 1]
$Drawer.close();
}
}
}
}
}
}
</script>

View File

@ -0,0 +1,81 @@
<template>
<Modal
ref="modal"
v-model="show"
:closable="escClosable"
:mask-closable="maskClosable"
:footer-hide="true"
:transition-names="[`drawer-fade-${placement}`, '']"
:beforeClose="beforeClose"
fullscreen
:class-name="`common-drawer-overlay ${placement}`">
<DrawerOverlayView
:placement="placement"
:size="size"
:minSize="minSize"
:resize="resize"
@on-close="onClose">
<slot/>
</DrawerOverlayView>
</Modal>
</template>
<script>
import DrawerOverlayView from "./view";
export default {
name: 'DrawerOverlay',
components: {DrawerOverlayView},
props: {
value: {
type: Boolean,
default: false
},
maskClosable: {
type: Boolean,
default: true
},
escClosable: {
type: Boolean,
default: true
},
placement: {
validator (value) {
return ['right', 'bottom'].includes(value)
},
default: 'bottom'
},
size: {
type: [Number, String],
default: "100%"
},
minSize: {
type: Number,
default: 300
},
resize: {
type: Boolean,
default: true
},
beforeClose: Function
},
data() {
return {
show: this.value,
}
},
watch: {
value(v) {
this.show = v;
},
show(v) {
this.value !== v && this.$emit("input", v)
}
},
methods: {
onClose() {
this.$refs.modal.close();
}
}
};
</script>

View File

@ -0,0 +1,113 @@
<template>
<div ref="body" class="overlay-body" :style="bodyStyle">
<div class="overlay-close">
<a href="javascript:void(0)" @click.stop="onClose">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" fill="none" role="img" class="icon fill-current">
<path d="M8.28596 6.51819C7.7978 6.03003 7.00634 6.03003 6.51819 6.51819C6.03003 7.00634 6.03003 7.7978 6.51819 8.28596L11.2322 13L6.51819 17.714C6.03003 18.2022 6.03003 18.9937 6.51819 19.4818C7.00634 19.97 7.7978 19.97 8.28596 19.4818L13 14.7678L17.714 19.4818C18.2022 19.97 18.9937 19.97 19.4818 19.4818C19.97 18.9937 19.97 18.2022 19.4818 17.714L14.7678 13L19.4818 8.28596C19.97 7.7978 19.97 7.00634 19.4818 6.51819C18.9937 6.03003 18.2022 6.03003 17.714 6.51819L13 11.2322L8.28596 6.51819Z" fill="currentColor"></path>
</svg>
</a>
</div>
<ResizeLine
v-if="resize"
class="overlay-resize"
v-model="dynamicSize"
:placement="placement"
:min="minSize"
:max="0"
:reverse="true"
:beforeResize="beforeResize"
@on-change="onChangeResize"/>
<div class="overlay-content"><slot/></div>
</div>
</template>
<script>
import ResizeLine from "../ResizeLine";
export default {
name: 'DrawerOverlayView',
components: {ResizeLine},
props: {
placement: {
validator (value) {
return ['right', 'bottom'].includes(value)
},
default: 'bottom'
},
size: {
type: [Number, String],
default: "100%"
},
minSize: {
type: Number,
default: 300
},
resize: {
type: Boolean,
default: true
},
},
data() {
return {
dynamicSize: 0,
}
},
computed: {
bodyStyle() {
let size = this.dynamicSize;
size = size <= 100 ? `${size}%` : `${size}px`
if (this.placement == 'right') {
return {
width: size,
height: "100%"
}
} else {
return {
width: "100%",
height: size,
}
}
}
},
watch: {
size: {
handler(val) {
this.dynamicSize = parseInt(val);
},
immediate: true
}
},
methods: {
onClose() {
this.$emit("on-close")
},
beforeResize() {
return new Promise(resolve => {
if (this.dynamicSize <= 100) {
this.updateSize();
}
resolve()
})
},
onChangeResize({event}) {
if (event === 'up') {
this.updateSize();
}
},
updateSize() {
if (this.placement === 'bottom') {
this.dynamicSize = this.$refs.body.clientHeight;
} else {
this.dynamicSize = this.$refs.body.clientWidth;
}
}
}
}
</script>

View File

@ -39,8 +39,6 @@ export default {
}, },
computed: { computed: {
...mapState(['cacheDrawerOverlay']),
style() { style() {
return { return {
top: this.y + 'px', top: this.y + 'px',
@ -79,20 +77,13 @@ export default {
if (!this.showTabbar) { if (!this.showTabbar) {
return true; return true;
} }
if (this.$Modal.visibles().length > 0) { return this.$Modal.visibles().length > 0;
return true;
}
return this.cacheDrawerOverlay.length > 0;
}, },
onBack() { onBack() {
if (this.$Modal.removeLast()) { if (this.$Modal.removeLast()) {
return; return;
} }
if (this.cacheDrawerOverlay.length > 0) {
this.cacheDrawerOverlay[this.cacheDrawerOverlay.length - 1].close();
return;
}
this.goBack(); this.goBack();
}, },

View File

@ -12,10 +12,6 @@ const stateData = {
// 数据缓存 // 数据缓存
cacheLoading: {}, cacheLoading: {},
// DrawerOverlay
cacheDrawerIndex: 0,
cacheDrawerOverlay: [],
// User // User
cacheUserActive: {}, cacheUserActive: {},
cacheUserWait: [], cacheUserWait: [],

View File

@ -1,26 +1,23 @@
.drawer-overlay { .common-drawer-overlay {
position: fixed; .ivu-modal {
top: 0; margin: 0;
left: 0; padding: 0;
width: 0;
height: 0;
z-index: 1000;
box-sizing: border-box;
pointer-events: none;
background: rgba(10, 10, 10, 0.76);
outline: none;
opacity: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
.overlay-mask { .ivu-modal-content {
position: absolute; background: transparent;
top: 0;
left: 0; .ivu-modal-close {
bottom: 0; display: none;
right: 0; }
z-index: 1;
.ivu-modal-body {
padding: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-content: flex-end;
}
}
} }
.overlay-body { .overlay-body {
@ -37,22 +34,27 @@
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
justify-content: flex-end; justify-content: flex-end;
> a { > a {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
color: #dbdbde; color: #fff;
.icon { .icon {
width: 24px; width: 24px;
height: 24px height: 24px
} }
> svg { > svg {
transition: all 0.3s; transition: all 0.3s;
} }
&:hover { &:hover {
color: #fff; color: #fff;
> svg { > svg {
transform: rotate(-90deg); transform: rotate(-90deg);
} }
@ -72,71 +74,65 @@
position: relative; position: relative;
background: #fff; background: #fff;
border-radius: 18px 18px 0 0; border-radius: 18px 18px 0 0;
transform: translate(0, 15%) scale(0.98); transform: translate(0, 0) scale(1);
cursor: default; cursor: default;
opacity: 0;
}
}
&.overlay-visible {
pointer-events: auto;
opacity: 1;
width: 100%;
height: 100%;
transition: opacity 0.2s ease;
.overlay-body {
.overlay-content {
opacity: 1;
transform: translate(0, 0) scale(1);
transition: opacity 0.2s ease, transform 0.3s ease;
}
}
}
&.overlay-hide {
width: 100%;
height: 100%;
transition: opacity 0.2s ease;
.overlay-body {
.overlay-content {
transform: translate(0, 15%) scale(0.98);
transition: opacity 0.2s ease, transform 0.2s ease
}
} }
} }
&.right { &.right {
flex-direction: row; .ivu-modal {
justify-content: flex-end; .ivu-modal-content {
.ivu-modal-body {
flex-direction: row;
}
}
}
.overlay-body { .overlay-body {
flex-direction: row; flex-direction: row;
.overlay-close { .overlay-close {
align-items: flex-start; align-items: flex-start;
} }
.overlay-resize { .overlay-resize {
width: 5px; width: 5px;
height: 100%; height: 100%;
margin-right: -5px; margin-right: -5px;
z-index: 1; z-index: 1;
} }
.overlay-content { .overlay-content {
transform: translate(15%, 0) scale(0.98);
border-radius: 18px 0 0 18px; border-radius: 18px 0 0 18px;
} }
} }
&.overlay-visible {
.overlay-body {
.overlay-content {
transform: translate(0, 0) scale(1);
}
}
}
&.overlay-hide {
.overlay-body {
.overlay-content {
transform: translate(15%, 0) scale(0.98);
}
}
}
} }
} }
.drawer-fade-bottom-enter-active {
transition: all .2s ease;
}
.drawer-fade-bottom-leave-active {
transition: all .2s ease;
}
.drawer-fade-bottom-enter,
.drawer-fade-bottom-leave-to {
transform: translate(0, 15%) scale(0.98);
opacity: 0;
}
.drawer-fade-right-enter-active {
transition: all .2s ease;
}
.drawer-fade-right-leave-active {
transition: all .2s ease;
}
.drawer-fade-right-enter,
.drawer-fade-right-leave-to {
transform: translate(15%, 0) scale(0.98);
opacity: 0;
}