refactor(components): [popover] switch to script-setup syntax (#8273)

This commit is contained in:
zz
2022-06-22 01:01:11 +08:00
committed by GitHub
parent 518db1e240
commit ed174ff73f
8 changed files with 149 additions and 167 deletions

View File

@@ -2,7 +2,7 @@ import { nextTick, ref } from 'vue'
import { afterEach, describe, expect, test } from 'vitest'
import makeMount from '@element-plus/test-utils/make-mount'
import { rAF } from '@element-plus/test-utils/tick'
import Popover from '../src/index.vue'
import Popover from '../src/popover.vue'
import PopoverDirective, { VPopover } from '../src/directive'
const AXIOM = 'Rem is the best girl'

View File

@@ -4,7 +4,7 @@ import { POPPER_CONTAINER_SELECTOR, useZIndex } from '@element-plus/hooks'
import makeMount from '@element-plus/test-utils/make-mount'
import { rAF } from '@element-plus/test-utils/tick'
import { ElPopperTrigger } from '@element-plus/components/popper'
import Popover from '../src/index.vue'
import Popover from '../src/popover.vue'
const AXIOM = 'Rem is the best girl'

View File

@@ -1,28 +1,16 @@
import Popover from './src/index.vue'
import { withInstall, withInstallDirective } from '@element-plus/utils'
import Popover from './src/popover.vue'
import PopoverDirective, { VPopover } from './src/directive'
import type { App } from 'vue'
import type { SFCWithInstall } from '@element-plus/utils'
export const ElPopoverDirective = withInstallDirective(
PopoverDirective,
VPopover
)
Popover.install = (app: App): void => {
app.component(Popover.name, Popover)
}
;(PopoverDirective as SFCWithInstall<typeof PopoverDirective>).install = (
app: App
) => {
app.directive(VPopover, PopoverDirective)
}
export const ElPopover = withInstall(Popover, {
directive: ElPopoverDirective,
})
export default ElPopover
const _PopoverDirective = PopoverDirective as SFCWithInstall<
typeof PopoverDirective
>
Popover.directive = _PopoverDirective
const _Popover = Popover as any as SFCWithInstall<typeof Popover> & {
directive: typeof _PopoverDirective
}
export default _Popover
export const ElPopover = _Popover
export const ElPopoverDirective = _PopoverDirective
export * from './src/popover'

View File

@@ -1,9 +1,8 @@
import type ElPopover from './index.vue'
import type { DirectiveBinding, ObjectDirective } from 'vue'
import type { PopoverInstance } from './popover'
const attachEvents = (el: HTMLElement, binding: DirectiveBinding) => {
const popperComponent: InstanceType<typeof ElPopover> =
binding.arg || binding.value
const popperComponent: PopoverInstance = binding.arg || binding.value
const popover = popperComponent?.popperRef
if (popover) {
popover.triggerRef = el

View File

@@ -1,136 +0,0 @@
<template>
<el-tooltip
ref="tooltipRef"
v-bind="$attrs"
:trigger="trigger"
:placement="placement"
:disabled="disabled"
:visible="visible"
:transition="transition"
:popper-options="popperOptions"
:tabindex="tabindex"
:content="content"
:offset="offset"
:show-after="showAfter"
:hide-after="hideAfter"
:auto-close="autoClose"
:show-arrow="showArrow"
:aria-label="title"
:effect="effect"
:enterable="enterable"
:popper-class="kls"
:popper-style="style"
:teleported="teleported"
:persistent="persistent"
:gpu-acceleration="gpuAcceleration"
@before-show="beforeEnter"
@before-hide="beforeLeave"
@show="afterEnter"
@hide="afterLeave"
>
<template v-if="$slots.reference">
<slot name="reference" />
</template>
<template #content>
<div v-if="title" :class="ns.e('title')" role="title">
{{ title }}
</div>
<slot>
{{ content }}
</slot>
</template>
</el-tooltip>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref } from 'vue'
import ElTooltip from '@element-plus/components/tooltip'
import { isString } from '@element-plus/utils'
import { useNamespace } from '@element-plus/hooks'
import { usePopoverProps } from './popover'
import type { StyleValue } from 'vue'
const emits = [
'update:visible',
'before-enter',
'before-leave',
'after-enter',
'after-leave',
]
const COMPONENT_NAME = 'ElPopover'
export default defineComponent({
name: COMPONENT_NAME,
components: {
ElTooltip,
},
props: usePopoverProps,
emits,
setup(props, { emit }) {
const ns = useNamespace('popover')
const tooltipRef = ref<InstanceType<typeof ElTooltip> | null>(null)
const popperRef = computed(() => {
return unref(tooltipRef)?.popperRef
})
const width = computed(() => {
if (isString(props.width)) {
return props.width as string
}
return `${props.width}px`
})
const style = computed(() => {
return [
{
width: width.value,
},
props.popperStyle,
] as StyleValue
})
const kls = computed(() => {
return [ns.b(), props.popperClass, { [ns.m('plain')]: !!props.content }]
})
const gpuAcceleration = computed(() => {
return props.transition === 'el-fade-in-linear'
})
const hide = () => {
tooltipRef.value?.hide()
}
const beforeEnter = () => {
emit('before-enter')
}
const beforeLeave = () => {
emit('before-leave')
}
const afterEnter = () => {
emit('after-enter')
}
const afterLeave = () => {
emit('update:visible', false)
emit('after-leave')
}
return {
ns,
kls,
gpuAcceleration,
style,
tooltipRef,
popperRef,
hide,
beforeEnter,
beforeLeave,
afterEnter,
afterLeave,
}
},
})
</script>

View File

@@ -1,11 +1,13 @@
import { buildProps } from '@element-plus/utils'
import { buildProps, isBoolean } from '@element-plus/utils'
import {
useTooltipContentProps,
useTooltipTriggerProps,
} from '@element-plus/components/tooltip'
import { dropdownProps } from '@element-plus/components/dropdown'
import type { ExtractPropTypes } from 'vue'
import type Popover from './popover.vue'
export const usePopoverProps = buildProps({
export const popoverProps = buildProps({
trigger: useTooltipTriggerProps.trigger,
placement: dropdownProps.placement,
disabled: useTooltipTriggerProps.disabled,
@@ -56,3 +58,15 @@ export const usePopoverProps = buildProps({
default: true,
},
} as const)
export type PopoverProps = ExtractPropTypes<typeof popoverProps>
export const popoverEmits = {
'update:visible': (value: boolean) => isBoolean(value),
'before-enter': () => true,
'before-leave': () => true,
'after-enter': () => true,
'after-leave': () => true,
}
export type PopoverEmits = typeof popoverEmits
export type PopoverInstance = InstanceType<typeof Popover>

View File

@@ -0,0 +1,109 @@
<template>
<el-tooltip
ref="tooltipRef"
v-bind="$attrs"
:trigger="trigger"
:placement="placement"
:disabled="disabled"
:visible="visible"
:transition="transition"
:popper-options="popperOptions"
:tabindex="tabindex"
:content="content"
:offset="offset"
:show-after="showAfter"
:hide-after="hideAfter"
:auto-close="autoClose"
:show-arrow="showArrow"
:aria-label="title"
:effect="effect"
:enterable="enterable"
:popper-class="kls"
:popper-style="style"
:teleported="teleported"
:persistent="persistent"
:gpu-acceleration="gpuAcceleration"
@before-show="beforeEnter"
@before-hide="beforeLeave"
@show="afterEnter"
@hide="afterLeave"
>
<template v-if="$slots.reference">
<slot name="reference" />
</template>
<template #content>
<div v-if="title" :class="ns.e('title')" role="title">
{{ title }}
</div>
<slot>
{{ content }}
</slot>
</template>
</el-tooltip>
</template>
<script lang="ts" setup>
import { computed, ref, unref } from 'vue'
import { ElTooltip } from '@element-plus/components/tooltip'
import { addUnit } from '@element-plus/utils'
import { useNamespace } from '@element-plus/hooks'
import { popoverEmits, popoverProps } from './popover'
import type { TooltipInstance } from '@element-plus/components/tooltip'
defineOptions({
name: 'ElPopover',
})
const props = defineProps(popoverProps)
const emit = defineEmits(popoverEmits)
const ns = useNamespace('popover')
const tooltipRef = ref<TooltipInstance>()
const popperRef = computed(() => {
return unref(tooltipRef)?.popperRef
})
const style = computed(() => {
return [
{
width: addUnit(props.width),
},
props.popperStyle!,
]
})
const kls = computed(() => {
return [ns.b(), props.popperClass!, { [ns.m('plain')]: !!props.content }]
})
const gpuAcceleration = computed(() => {
return props.transition === 'el-fade-in-linear'
})
const hide = () => {
tooltipRef.value?.hide()
}
const beforeEnter = () => {
emit('before-enter')
}
const beforeLeave = () => {
emit('before-leave')
}
const afterEnter = () => {
emit('after-enter')
}
const afterLeave = () => {
emit('update:visible', false)
emit('after-leave')
}
defineExpose({
/** @description popper ref */
popperRef,
/** @description hide popover */
hide,
})
</script>

View File

@@ -30,6 +30,14 @@ export const withInstallFunction = <T>(fn: T, name: string) => {
return fn as SFCInstallWithContext<T>
}
export const withInstallDirective = <T>(directive: T, name: string) => {
;(directive as SFCWithInstall<T>).install = (app: App): void => {
app.directive(name, directive)
}
return directive as SFCWithInstall<T>
}
export const withNoopInstall = <T>(component: T) => {
;(component as SFCWithInstall<T>).install = NOOP