mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(hooks): feat: Encapsulate function for rendering teleport element
- Add new function for rendering teleport element.
This commit is contained in:
60
packages/hooks/use-teleport/index.ts
Normal file
60
packages/hooks/use-teleport/index.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
34
packages/utils/global-nodes.ts
Normal file
34
packages/utils/global-nodes.ts
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user