feat(hooks): feat: Encapsulate function for rendering teleport element

- Add new function for rendering teleport element.
This commit is contained in:
jeremywuuuuu
2021-06-23 16:32:48 +08:00
committed by hangzou
parent d754934ebd
commit 74ec002d23
3 changed files with 95 additions and 1 deletions

View File

@@ -0,0 +1,60 @@
import { h, ref, Teleport, getCurrentInstance, onMounted } from 'vue'
import { NOOP } from '@vue/shared'
import isServer from '@element-plus/utils/isServer'
import { createGlobalNode, removeGlobalNode } from '@element-plus/utils/global-nodes'
import type { VNode } from 'vue'
export default (contentRenderer: () => VNode, appendToBody: boolean) => {
const vm = getCurrentInstance()
const isTeleportVisible = ref(false)
if (isServer) {
return {
isTeleportVisible,
showTeleport: NOOP,
hideTeleport: NOOP,
renderTeleport: NOOP,
}
}
const target = (vm.proxy.$props as { target: string; }).target
let $el: HTMLElement = null
const showTeleport = () => {
isTeleportVisible.value = true
$el = createGlobalNode()
}
const hideTeleport = () => {
isTeleportVisible.value = true
removeGlobalNode($el)
$el = null
}
const renderTeleport = () => {
return appendToBody !== true
? contentRenderer()
: isTeleportVisible.value === true
? [
h(
Teleport,
{ to: target },
contentRenderer(),
),
]
: void 0
}
onMounted(hideTeleport)
return {
isTeleportVisible,
showTeleport,
hideTeleport,
renderTeleport,
}
}

View File

@@ -3,7 +3,7 @@ import { NOOP } from '@vue/shared'
import { stop } from '@element-plus/utils/dom'
import type { VNode, Ref } from 'vue'
import type { Effect } from '../use-popper/defaults'
import type { Effect } from '@element-plus/internal/props/use-popper-props'
interface IRenderPopperProps {
effect: Effect

View File

@@ -0,0 +1,34 @@
import isServer from './isServer'
const globalNodes = []
let target = isServer ? void 0 : document.body
export function createGlobalNode(id?: string) {
const el = document.createElement('div')
if (id !== void 0) {
el.id = id
}
target.appendChild(el)
globalNodes.push(el)
return el
}
export function removeGlobalNode(el: HTMLElement) {
globalNodes.splice(globalNodes.indexOf(el), 1)
el.remove()
}
export function changeGlobalNodesTarget(el: HTMLElement) {
if (el !== target) {
target = el
globalNodes.forEach(el => {
if (el.contains(target) === false) {
target.appendChild(el)
}
})
}
}