1
- import { defineComponent , reactive , ref , onMounted , onBeforeUnmount , renderSlot , useSlots } from 'vue'
2
- import { tooltipProps } from './tooltip-types'
3
- import './tooltip.scss'
1
+ import { defineComponent , ref , Teleport , toRefs , Transition } from 'vue' ;
2
+ import { FlexibleOverlay } from '../../overlay' ;
3
+ import { TooltipProps , tooltipProps } from './tooltip-types' ;
4
+ import { useTooltip } from './use-tooltip' ;
5
+ import './tooltip.scss' ;
4
6
5
7
export default defineComponent ( {
6
8
name : 'DTooltip' ,
7
9
props : tooltipProps ,
8
- setup ( props ) {
9
- const position = reactive ( {
10
- left : 0 ,
11
- top : 0
12
- } )
13
- // 设置tooltip箭头的样式
14
- const arrowStyle = ( attr , value ) => {
15
- document . getElementById ( 'devui-arrow' ) . style [ attr ] = value
16
- }
10
+ setup ( props : TooltipProps , { slots } ) {
11
+ const { showAnimation, content } = toRefs ( props ) ;
12
+ const origin = ref < HTMLElement > ( ) ;
13
+ const tooltipRef = ref < HTMLElement > ( ) ;
14
+ const { visible, placement, positionArr, overlayStyles, onPositionChange } = useTooltip ( origin , props ) ;
17
15
18
- const slotElement = ref ( null )
19
- onMounted ( ( ) => {
20
- slotElement . value . children [ 0 ] . onmouseenter = function ( ) {
21
- // 创建tooltip元素(外层容器、箭头、内容)
22
- const tooltip = document . createElement ( 'div' )
23
- const arrow = document . createElement ( 'div' )
24
- const tooltipcontent = document . createElement ( 'div' )
25
- // 设置tooltip的样式
26
- tooltip . classList . add ( 'tooltip' )
27
- arrow . classList . add ( 'arrow' )
28
- tooltipcontent . classList . add ( 'tooltipcontent' )
29
- // 设置tooltip的id
30
- arrow . id = 'devui-arrow'
31
- tooltip . id = 'devui-tooltip1'
32
-
33
- setTimeout ( ( ) => {
34
- document . getElementById ( 'devui-tooltip' ) . appendChild ( tooltip )
35
- tooltip . appendChild ( arrow )
36
- tooltip . appendChild ( tooltipcontent )
37
- tooltipcontent . innerHTML = props . content
38
-
39
- tooltip . style . opacity = '1'
40
- tooltip . style . zIndex = '999'
41
- arrow . style . border = '5px solid transparent'
42
- switch ( props . position ) {
43
- case 'top' :
44
- position . left = ( slotElement . value . children [ 0 ] . offsetLeft - tooltip . offsetWidth / 2 + slotElement . value . children [ 0 ] . offsetWidth / 2 ) - 5 ;
45
- position . top = slotElement . value . children [ 0 ] . offsetTop - 10 - tooltipcontent . offsetHeight
46
- // 设置箭头的样式
47
- // arrowStyle('borderTop', '5px solid rgb(70, 77, 110)')
48
- arrow . style . top = `${ tooltipcontent . offsetHeight } px`
49
- arrow . style . left = `${ tooltipcontent . offsetWidth / 2 + 5 } px`
50
- arrow . style . borderTop = '5px solid rgb(70, 77, 110)'
51
- break ;
52
- case 'bottom' :
53
- position . top = slotElement . value . children [ 0 ] . offsetHeight + slotElement . value . children [ 0 ] . offsetTop + 10
54
- position . left = ( slotElement . value . children [ 0 ] . offsetLeft + slotElement . value . children [ 0 ] . offsetWidth / 2 - tooltipcontent . offsetWidth / 2 ) - 5 ;
55
- // 设置arrow.value的样式
56
- arrowStyle ( 'borderBottom' , '5px solid rgb(70, 77, 110)' )
57
- arrow . style . top = '-10px'
58
- arrow . style . left = `${ tooltipcontent . offsetWidth / 2 + 5 } px`
59
- arrow . style . borderBottom = '5px solid rgb(70, 77, 110)'
60
- break ;
61
- case 'left' :
62
- position . top = slotElement . value . children [ 0 ] . offsetTop + slotElement . value . children [ 0 ] . offsetHeight / 2 - tooltipcontent . offsetHeight / 2
63
- position . left = slotElement . value . children [ 0 ] . offsetLeft - 20 - tooltipcontent . offsetWidth
64
- // 设置arrow.value的样式
65
- arrowStyle ( 'borderLeft' , '5px solid rgb(70, 77, 110)' )
66
- arrow . style . left = `${ tooltipcontent . offsetWidth + 10 } px`
67
- arrow . style . top = `${ tooltipcontent . offsetHeight / 2 - 5 } px`
68
- arrow . style . borderLeft = '5px solid rgb(70, 77, 110)'
69
- break ;
70
- case 'right' :
71
- // 设置tooltip 内容的样式
72
- position . left = slotElement . value . children [ 0 ] . offsetLeft + slotElement . value . children [ 0 ] . offsetWidth
73
- position . top = slotElement . value . children [ 0 ] . offsetTop + slotElement . value . children [ 0 ] . offsetHeight / 2 - tooltipcontent . offsetHeight / 2
74
- // 设置箭头的样式
75
- arrowStyle ( 'borderRight' , '5px solid rgb(70, 77, 110)' )
76
- arrow . style . top = `${ tooltipcontent . offsetHeight / 2 - 5 } px`
77
- arrow . style . left = '-0px'
78
- arrow . style . borderRight = '5px solid rgb(70, 77, 110)'
79
- break ;
80
- }
81
- tooltip . style . top = position . top + 5 + 'px'
82
- tooltip . style . left = position . left + 'px'
83
- } , props . mouseEnterDelay )
84
- }
85
- slotElement . value . children [ 0 ] . onmouseleave = function ( ) {
86
- setTimeout ( ( ) => {
87
- document . getElementById ( 'devui-tooltip1' ) . removeChild ( document . getElementById ( 'devui-arrow' ) )
88
- document . getElementById ( 'devui-tooltip' ) . removeChild ( document . getElementById ( 'devui-tooltip1' ) )
89
- } , props . mouseLeaveDelay )
90
- }
91
- } )
92
-
93
- onBeforeUnmount ( ( ) => {
94
- slotElement . value . children [ 0 ] . onmouseenter = null
95
- slotElement . value . children [ 0 ] . onmouseleave = null
96
- } )
97
-
98
- return ( ) => {
99
- const defaultSlot = renderSlot ( useSlots ( ) , 'default' )
100
- return (
101
- < div class = "devui-tooltip" id = 'devui-tooltip' >
102
- < div class = 'slotElement' ref = { slotElement } >
103
- { defaultSlot }
104
- </ div >
16
+ return ( ) => (
17
+ < >
18
+ < div ref = { origin } class = 'devui-tooltip-reference' >
19
+ { slots . default ?.( ) }
105
20
</ div >
106
- )
107
- }
108
- }
109
- } ) ;
21
+ < Teleport to = 'body' >
22
+ < Transition name = { showAnimation . value ? `devui-tooltip-fade-${ placement . value } ` : '' } >
23
+ < FlexibleOverlay
24
+ v-model = { visible . value }
25
+ ref = { tooltipRef }
26
+ class = 'devui-tooltip'
27
+ origin = { origin . value }
28
+ position = { positionArr . value }
29
+ offset = { 6 }
30
+ show-arrow
31
+ style = { overlayStyles . value }
32
+ onPositionChange = { onPositionChange } >
33
+ < span innerHTML = { content . value } > </ span >
34
+ </ FlexibleOverlay >
35
+ </ Transition >
36
+ </ Teleport >
37
+ </ >
38
+ ) ;
39
+ } ,
40
+ } ) ;
0 commit comments