fix(Popup): teleport

This commit is contained in:
chenjiahan 2020-07-06 15:12:56 +08:00
parent 7087922d18
commit 6995bcc8a3
3 changed files with 43 additions and 67 deletions

View File

@ -8,7 +8,6 @@ import { getScroller } from '../../utils/dom/scroll';
// Mixins
import { TouchMixin } from '../touch';
import { PortalMixin } from '../portal';
import { CloseOnPopstateMixin } from '../close-on-popstate';
export const popupMixinProps = {
@ -20,6 +19,8 @@ export const popupMixinProps = {
overlayStyle: Object,
// overlay custom class name
overlayClass: String,
// teleport
getContainer: [String, Function],
// whether to close popup when click overlay
closeOnClickOverlay: Boolean,
// z-index
@ -41,7 +42,6 @@ export function PopupMixin(options = {}) {
mixins: [
TouchMixin,
CloseOnPopstateMixin,
PortalMixin({}),
],
props: popupMixinProps,

View File

@ -1,47 +0,0 @@
function getElement(selector) {
if (typeof selector === 'string') {
return document.querySelector(selector);
}
return selector();
}
export function PortalMixin({ ref, afterPortal }) {
return {
props: {
getContainer: [String, Function],
},
watch: {
getContainer: 'portal',
},
mounted() {
if (this.getContainer) {
this.portal();
}
},
methods: {
portal() {
const { getContainer } = this;
const el = ref ? this.$refs[ref] : this.$el;
let container;
if (getContainer) {
container = getElement(getContainer);
} else if (this.$parent) {
container = this.$parent.$el;
}
if (container && container !== el.parentNode) {
container.appendChild(el);
}
if (afterPortal) {
afterPortal.call(this);
}
},
},
};
}

View File

@ -1,5 +1,5 @@
import { Transition } from 'vue';
import { createNamespace, isDef } from '../utils';
import { Teleport, Transition } from 'vue';
import { createNamespace, isDef, isFunction } from '../utils';
import { PopupMixin } from '../mixins/popup';
import Icon from '../icon';
import Overlay from '../overlay';
@ -48,25 +48,28 @@ export default createComponent({
this.onClosed = createEmitter('closed');
},
render() {
const { round, position, duration } = this;
const isCenter = position === 'center';
methods: {
genOverlay() {
if (this.overlay) {
return <Overlay show={this.show} onClick={this.onClickOverlay} />;
}
},
const transitionName =
this.transition ||
(isCenter ? 'van-fade' : `van-popup-slide-${position}`);
genPopup() {
const { round, position, duration } = this;
const isCenter = position === 'center';
const style = {};
if (isDef(duration)) {
const key = isCenter ? 'animationDuration' : 'transitionDuration';
style[key] = `${duration}s`;
}
const transitionName =
this.transition ||
(isCenter ? 'van-fade' : `van-popup-slide-${position}`);
return (
<>
{this.overlay && (
<Overlay show={this.show} onClick={this.onClickOverlay} />
)}
const style = {};
if (isDef(duration)) {
const key = isCenter ? 'animationDuration' : 'transitionDuration';
style[key] = `${duration}s`;
}
return (
<Transition
name={transitionName}
onAfterEnter={this.onOpened}
@ -98,6 +101,26 @@ export default createComponent({
</div>
) : null}
</Transition>
);
},
},
render() {
const { getContainer } = this;
if (getContainer) {
const to = isFunction(getContainer) ? getContainer() : getContainer;
return (
<Teleport to={to}>
{this.genOverlay()}
{this.genPopup()}
</Teleport>
);
}
return (
<>
{this.genOverlay()}
{this.genPopup()}
</>
);
},