From 0438af4254133e10bb107efb487caf475ca327b5 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Thu, 2 Sep 2021 01:09:11 +0800 Subject: [PATCH 1/6] =?UTF-8?q?tooltip=E6=8F=90=E7=A4=BA=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 1 + devui/toast/src/toast.tsx | 1 + devui/tooltip/index.ts | 16 ++ devui/tooltip/src/tooltip-types.ts | 31 ++++ devui/tooltip/src/tooltip.scss | 23 +++ devui/tooltip/src/tooltip.tsx | 162 +++++++++++++++++++++ devui/tooltip/utils/EventListener.js | 21 +++ sites/components/toast/index.md | 1 + sites/components/tooltip/index.md | 210 +++++++++++++++++++++++++++ 9 files changed, 466 insertions(+) create mode 100644 devui/tooltip/index.ts create mode 100644 devui/tooltip/src/tooltip-types.ts create mode 100644 devui/tooltip/src/tooltip.scss create mode 100644 devui/tooltip/src/tooltip.tsx create mode 100644 devui/tooltip/utils/EventListener.js create mode 100644 sites/components/tooltip/index.md diff --git a/.eslintrc.js b/.eslintrc.js index 3da2f803..95881cad 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,4 @@ + module.exports = { parser: 'vue-eslint-parser', parserOptions: { diff --git a/devui/toast/src/toast.tsx b/devui/toast/src/toast.tsx index 11d0c886..eacdc7bc 100644 --- a/devui/toast/src/toast.tsx +++ b/devui/toast/src/toast.tsx @@ -1,3 +1,4 @@ + import './toast.scss' import { computed, defineComponent, nextTick, onUnmounted, ref, watch } from 'vue' diff --git a/devui/tooltip/index.ts b/devui/tooltip/index.ts new file mode 100644 index 00000000..b5b67564 --- /dev/null +++ b/devui/tooltip/index.ts @@ -0,0 +1,16 @@ +import type { App } from 'vue' +import Tooltip from './src/tooltip' + +Tooltip.install = function(app: App) { + app.component(Tooltip.name, Tooltip) +} + +export { Tooltip } + +export default { + title: 'Tooltip tooltip提示', + category: '反馈', + install(app: App): void { + app.use(Tooltip as any) + } +} diff --git a/devui/tooltip/src/tooltip-types.ts b/devui/tooltip/src/tooltip-types.ts new file mode 100644 index 00000000..0045bec5 --- /dev/null +++ b/devui/tooltip/src/tooltip-types.ts @@ -0,0 +1,31 @@ +import type { PropType, ExtractPropTypes } from 'vue' + +export type DevTooltip = 'top' | 'right' | 'bottom' | 'left'; +export const DevTooltipShowAnimation = true; + +export const tooltipProps = { + /* test: { + type: Object as PropType<{ xxx: xxx }> + } */ + position: { + type: String, + default: 'top' + }, + showAnimation: { + type: Boolean, + default: true + }, + content: { + type: String + }, + mouseLeaveDelay: { + type: String, + default: '150' + }, + mouseEnterDelay: { + type: String, + default: '100' + } +} as const + +export type TooltipProps = ExtractPropTypes diff --git a/devui/tooltip/src/tooltip.scss b/devui/tooltip/src/tooltip.scss new file mode 100644 index 00000000..52dd4685 --- /dev/null +++ b/devui/tooltip/src/tooltip.scss @@ -0,0 +1,23 @@ +.d-tooltip { + box-sizing: border-box; + position: relative; + .tooltip { + box-sizing: border-box; + position: absolute; + width: fit-content; + transition: all 0.5s; + .arrow { + width: 0; + height: 0; + position: absolute; + } + .tooltipcontent { + box-sizing: border-box; + padding: 10px; + margin-left: 10px; + width: fit-content; + background-color: rgb(51, 51, 51); + color: #fff; + } + } +} diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx new file mode 100644 index 00000000..3237e2bf --- /dev/null +++ b/devui/tooltip/src/tooltip.tsx @@ -0,0 +1,162 @@ +import './tooltip.scss' + +import { defineComponent, onMounted, } from 'vue' +import { tooltipProps, TooltipProps } from './tooltip-types' +import EventListener from '../utils/EventListener' + +/** + * 使用: + * + * + */ +export default defineComponent({ + name: 'DTooltip', + props: tooltipProps, + emits: [], + data (){ + return { + position: { + top: 0, + left: 0 + }, + show: false + } + }, + methods: { + // 延迟演示 默认100ms + delayShowTrue (fn, delay){ + let start; + if (parseInt(delay)>=0){ + return function (){ + if (start){ + clearTimeout(start); + } + start = setTimeout(fn, parseInt(delay)); + }; + } else{ + console.error('the value of delay is bigger than 0 and the type of delay must be string!'); + return + } + }, + // 延迟消失,默认150ms + delayShowFalse (fn, delay){ + if (this.show && parseInt(delay) >= 0){ + setTimeout(fn, parseInt(delay)); + } + } + }, + watch: { + show: function (newValue){ + if (newValue){ + // 鼠标悬浮为true,显示提示框 + this.$refs.tooltip.style.opacity = '1'; + const popover = this.$refs.tooltip; // 获取提示框组件 + const arrow = this.$refs.arrow; // 提示框组件箭头 + const triger = this.$refs.slotElement.children[0] // slot元素 + // 具体的判定规则 + switch (this.props.position){ + case 'top': + // 设置 tooltip 内容的样式 + this.position.left = triger.offsetLeft - popover.offsetWidth / 2 + triger.offsetWidth / 2; + this.position.top = `${triger.offsetTop - 10 - this.$refs.tooltipcontent.offsetHeight}`; + // 设置箭头的样式 + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid cornflowerblue'; + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight}px`; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 5}px`; + break; + + case 'right': + // 设置tooltip 内容的样式 + this.position.left = triger.offsetLeft + triger.offsetWidth; + this.position.top = triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2; + // 设置箭头的样式 + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.borderRight = '10px solid cornflowerblue'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; + arrow.style.left = '-10px'; + break; + + case 'bottom': + // 设置tooltip的样式 + this.position.top = `${triger.offsetHeight + triger.offsetTop + 10}`; + this.position.left = `${triger.offsetLeft + triger.offsetWidth/2 - this.$refs.tooltipcontent.offsetWidth/2}`; + // 设置arrow的样式 + arrow.style.borderBottom = '10px solid orange'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.top = `${-20}px`; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 10}px`; + break; + + case 'left': + this.position.top = `${triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2}`; + this.position.left = `${triger.offsetLeft - 20 - this.$refs.tooltipcontent.offsetWidth}`; + // 设置arrow的样式 + arrow.style.borderLeft = '10px solid cornflowerblue'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth + 10}px` + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; + break; + + default: + console.error('The attribute position value is wrong, the value is one of top、right、left、bottom'); + break; + }; + popover.style.top = this.position.top + 'px'; + popover.style.left = this.position.left + 'px'; + } else { + this.position.top = 0; + this.position.left = 0; + // 鼠标移走为false,隐藏提示框 + this.$refs.tooltip.style.opacity = '0'; + } + } + }, + mounted (){ + const self = this; + const slotEle = this.$refs.slotElement.children[0]; + // 初次渲染不显示 + if (!show){ + this.$refs.tooltip.style.opacity = '0'; + } + // 注册鼠标引入事件 + this.enterEvent = EventListener.listen(slotEle, 'mouseenter', self.delayShowTrue(function (){ + self.show = true; + }, self.mouseEnterDelay || 100)); + + // 注册鼠标移除事件 + this.leaveEvent = EventListener.listen(slotEle, 'mouseleave', self.delayShowFalse(function (){ + self.show = false; + },self.mouseLeaveDelay || 150)); + + }, + beforeUnmount (){ + this.enterEvent.remove(); + this.leaveEvent.remove(); + }, + render() { + const {} = this + + return ( +
+
+ +
/** slot 元素 */ +
/** tooltip 提示框 */ +
/** tooltip 提示框箭头 */ +
+ {{content}} +
/** tooltip提示的内容 */ +
+
+ ); + } +}) diff --git a/devui/tooltip/utils/EventListener.js b/devui/tooltip/utils/EventListener.js new file mode 100644 index 00000000..73f6f68c --- /dev/null +++ b/devui/tooltip/utils/EventListener.js @@ -0,0 +1,21 @@ +const EventListener = { + listen: function (target, eventType, callback) { + if (target.addEventListener){ + target.addEventListener(eventType, callback, false); + return { + remove (){ + target.removeEventListener(target, callback, false); + } + } + } else { + target.attchEvent(eventType, callback); + return { + remove (){ + target.detachEvent(eventType, callback); + } + }; + } + } +}; + +export default EventListener; \ No newline at end of file diff --git a/sites/components/toast/index.md b/sites/components/toast/index.md index 2218666a..40b5474a 100644 --- a/sites/components/toast/index.md +++ b/sites/components/toast/index.md @@ -1,3 +1,4 @@ + # Toast 全局通知 全局信息提示组件。 diff --git a/sites/components/tooltip/index.md b/sites/components/tooltip/index.md new file mode 100644 index 00000000..8427c000 --- /dev/null +++ b/sites/components/tooltip/index.md @@ -0,0 +1,210 @@ + +# Tooltip 提示 + +文字提示组件。 + +### 何时使用 + +用户鼠标移动到文字上,需要进一步的提示时使用。 + +### 基本用法 + +```html +
+ + + + + + + + + + + + +
+``` + +```scss +.d-tooltip { + box-sizing: border-box; + position: relative; + .tooltip { + box-sizing: border-box; + position: absolute; + width: fit-content; + transition: all 0.5s; + .arrow { + width: 0; + height: 0; + position: absolute; + } + .tooltipcontent { + box-sizing: border-box; + padding: 10px; + margin-left: 10px; + width: fit-content; + background-color: rgb(51, 51, 51); + color: #fff; + } + } +} +``` + +```ts +export default defineComponent({ + name: 'DTooltip', + props: tooltipProps, + emits: [], + data (){ + return { + position: { + top: 0, + left: 0 + }, + show: false + } + }, + methods: { + // 延迟演示 默认100ms + delayShowTrue (fn, delay){ + let start; + if (parseInt(delay)>=0){ + return function (){ + if (start){ + clearTimeout(start); + } + start = setTimeout(fn, parseInt(delay)); + }; + } else{ + console.error('the value of delay is bigger than 0 and the type of delay must be string!'); + return + } + }, + // 延迟消失,默认150ms + delayShowFalse (fn, delay){ + if (this.show && parseInt(delay) >= 0){ + setTimeout(fn, parseInt(delay)); + } + } + }, + watch: { + show: function (newValue){ + if (newValue){ + // 鼠标悬浮为true,显示提示框 + this.$refs.tooltip.style.opacity = '1'; + const popover = this.$refs.tooltip; // 获取提示框组件 + const arrow = this.$refs.arrow; // 提示框组件箭头 + const triger = this.$refs.slotElement.children[0] // slot元素 + // 具体的判定规则 + switch (this.props.position){ + case 'top': + // 设置 tooltip 内容的样式 + this.position.left = triger.offsetLeft - popover.offsetWidth / 2 + triger.offsetWidth / 2; + this.position.top = `${triger.offsetTop - 10 - this.$refs.tooltipcontent.offsetHeight}`; + // 设置箭头的样式 + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid cornflowerblue'; + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight}px`; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 5}px`; + break; + + case 'right': + // 设置tooltip 内容的样式 + this.position.left = triger.offsetLeft + triger.offsetWidth; + this.position.top = triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2; + // 设置箭头的样式 + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.borderRight = '10px solid cornflowerblue'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; + arrow.style.left = '-10px'; + break; + + case 'bottom': + // 设置tooltip的样式 + this.position.top = `${triger.offsetHeight + triger.offsetTop + 10}`; + this.position.left = `${triger.offsetLeft + triger.offsetWidth/2 - this.$refs.tooltipcontent.offsetWidth/2}`; + // 设置arrow的样式 + arrow.style.borderBottom = '10px solid orange'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.borderLeft = '10px solid transparent'; + arrow.style.top = `${-20}px`; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 10}px`; + break; + + case 'left': + this.position.top = `${triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2}`; + this.position.left = `${triger.offsetLeft - 20 - this.$refs.tooltipcontent.offsetWidth}`; + // 设置arrow的样式 + arrow.style.borderLeft = '10px solid cornflowerblue'; + arrow.style.borderRight = '10px solid transparent'; + arrow.style.borderBottom = '10px solid transparent'; + arrow.style.borderTop = '10px solid transparent'; + arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth + 10}px` + arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; + break; + + default: + console.error('The attribute position value is wrong, the value is one of top、right、left、bottom'); + break; + }; + popover.style.top = this.position.top + 'px'; + popover.style.left = this.position.left + 'px'; + } else { + this.position.top = 0; + this.position.left = 0; + // 鼠标移走为false,隐藏提示框 + this.$refs.tooltip.style.opacity = '0'; + } + } + }, + mounted (){ + const self = this; + const slotEle = this.$refs.slotElement.children[0]; + // 初次渲染不显示 + if (!show){ + this.$refs.tooltip.style.opacity = '0'; + } + // 注册鼠标引入事件 + this.enterEvent = EventListener.listen(slotEle, 'mouseenter', self.delayShowTrue(function (){ + self.show = true; + }, self.mouseEnterDelay || 100)); + + // 注册鼠标移除事件 + this.leaveEvent = EventListener.listen(slotEle, 'mouseleave', self.delayShowFalse(function (){ + self.show = false; + },self.mouseLeaveDelay || 150)); + + }, + beforeUnmount (){ + this.enterEvent.remove(); + this.leaveEvent.remove(); + }, + render() { + const {} = this + + return ( +
+
+ +
/** slot 元素 */ +
/** tooltip 提示框 */ +
/** tooltip 提示框箭头 */ +
+ {{content}} +
/** tooltip提示的内容 */ +
+
+ ); + } +}) +``` + +### 延时触发 + -- Gitee From 87f9ee841730cd3d7e49930e4c32f751a78606f9 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 16:31:02 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0tooltip=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.tsx | 296 ++++++++++++++------------- devui/tooltip/utils/EventListener.js | 2 + sites/components/tabs/index.md | 1 + sites/components/tooltip/index.md | 163 +-------------- 4 files changed, 163 insertions(+), 299 deletions(-) diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index 3237e2bf..dda31c7d 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -1,6 +1,6 @@ import './tooltip.scss' -import { defineComponent, onMounted, } from 'vue' +import { defineComponent, reactive, ref, watch, onMounted, getCurrentInstance, onBeforeUnmount, renderSlot, useSlots} from 'vue' import { tooltipProps, TooltipProps } from './tooltip-types' import EventListener from '../utils/EventListener' @@ -10,153 +10,161 @@ import EventListener from '../utils/EventListener' * */ export default defineComponent({ - name: 'DTooltip', - props: tooltipProps, - emits: [], - data (){ - return { - position: { - top: 0, - left: 0 - }, - show: false - } - }, - methods: { - // 延迟演示 默认100ms - delayShowTrue (fn, delay){ - let start; - if (parseInt(delay)>=0){ - return function (){ - if (start){ - clearTimeout(start); - } - start = setTimeout(fn, parseInt(delay)); - }; - } else{ - console.error('the value of delay is bigger than 0 and the type of delay must be string!'); - return - } - }, - // 延迟消失,默认150ms - delayShowFalse (fn, delay){ - if (this.show && parseInt(delay) >= 0){ - setTimeout(fn, parseInt(delay)); - } - } - }, - watch: { - show: function (newValue){ - if (newValue){ - // 鼠标悬浮为true,显示提示框 - this.$refs.tooltip.style.opacity = '1'; - const popover = this.$refs.tooltip; // 获取提示框组件 - const arrow = this.$refs.arrow; // 提示框组件箭头 - const triger = this.$refs.slotElement.children[0] // slot元素 - // 具体的判定规则 - switch (this.props.position){ - case 'top': - // 设置 tooltip 内容的样式 - this.position.left = triger.offsetLeft - popover.offsetWidth / 2 + triger.offsetWidth / 2; - this.position.top = `${triger.offsetTop - 10 - this.$refs.tooltipcontent.offsetHeight}`; - // 设置箭头的样式 - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid cornflowerblue'; - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight}px`; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 5}px`; - break; - - case 'right': - // 设置tooltip 内容的样式 - this.position.left = triger.offsetLeft + triger.offsetWidth; - this.position.top = triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2; - // 设置箭头的样式 - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.borderRight = '10px solid cornflowerblue'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; - arrow.style.left = '-10px'; - break; + name: 'DTooltip', + props: tooltipProps, + setup(props, ctx){ + let position = reactive({ + left: 0, + top: 0 + }); + let show = ref(false); - case 'bottom': - // 设置tooltip的样式 - this.position.top = `${triger.offsetHeight + triger.offsetTop + 10}`; - this.position.left = `${triger.offsetLeft + triger.offsetWidth/2 - this.$refs.tooltipcontent.offsetWidth/2}`; - // 设置arrow的样式 - arrow.style.borderBottom = '10px solid orange'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.top = `${-20}px`; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 10}px`; - break; + // slotElement元素的ref + let slotElement = ref(null); + // tooltip元素的引用 + let tooltip = ref(null); + // arrow元素的引用 + let arrow = ref(null); + // tooltipcontent的引用 + let tooltipcontent = ref(null); - case 'left': - this.position.top = `${triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2}`; - this.position.left = `${triger.offsetLeft - 20 - this.$refs.tooltipcontent.offsetWidth}`; - // 设置arrow的样式 - arrow.style.borderLeft = '10px solid cornflowerblue'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth + 10}px` - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; - break; + let enterEvent; + let leaveEvent; - default: - console.error('The attribute position value is wrong, the value is one of top、right、left、bottom'); - break; + // 延迟显示 + const delayShowTrue = function (fn, delay){ + let start; + if (parseInt(delay)>=0){ + return function (){ + if (start){ + clearTimeout(start); + } + start = setTimeout(fn, parseInt(delay)); + }; + } else{ + console.error('the value of delay is bigger than 0 and the type of delay must be string!'); + return + } + }; + // 延迟消失 + const delayShowFalse = function (fn, delay){ + if (show.value && parseInt(delay) >= 0){ + setTimeout(fn, parseInt(delay)); + } }; - popover.style.top = this.position.top + 'px'; - popover.style.left = this.position.left + 'px'; - } else { - this.position.top = 0; - this.position.left = 0; - // 鼠标移走为false,隐藏提示框 - this.$refs.tooltip.style.opacity = '0'; - } - } - }, - mounted (){ - const self = this; - const slotEle = this.$refs.slotElement.children[0]; - // 初次渲染不显示 - if (!show){ - this.$refs.tooltip.style.opacity = '0'; - } - // 注册鼠标引入事件 - this.enterEvent = EventListener.listen(slotEle, 'mouseenter', self.delayShowTrue(function (){ - self.show = true; - }, self.mouseEnterDelay || 100)); - // 注册鼠标移除事件 - this.leaveEvent = EventListener.listen(slotEle, 'mouseleave', self.delayShowFalse(function (){ - self.show = false; - },self.mouseLeaveDelay || 150)); + onMounted(()=>{ + // 组件初始化不渲染tooltip + if (!show.value){ + tooltip.value.style.opacity = '0'; + }; - }, - beforeUnmount (){ - this.enterEvent.remove(); - this.leaveEvent.remove(); - }, - render() { - const {} = this + // 注册鼠标引入事件 + enterEvent = EventListener.listen(slotElement.value.children[0], 'mouseenter', function (){ + show.value = true; + }); - return ( -
-
- -
/** slot 元素 */ -
/** tooltip 提示框 */ -
/** tooltip 提示框箭头 */ -
- {{content}} -
/** tooltip提示的内容 */ -
-
- ); - } -}) + // 注册鼠标移除事件 + leaveEvent = EventListener.listen(slotElement.value.children[0], 'mouseleave', function (){ + show.value = false; + }); + }); + + watch(show, function (newValue, oldValue){ + if (newValue){ + // 鼠标悬浮为true,显示提示框 + tooltip.value.style.opacity = '1'; + tooltip.value.style.zIndex = '500'; + // 具体的判定规则 + switch (props.position){ + case 'top': + // 设置 tooltip 内容的样式 + position.left = slotElement.value.children[0].offsetLeft - tooltip.value.offsetWidth / 2 + slotElement.value.children[0].offsetWidth / 2; + position.top = slotElement.value.children[0].offsetTop - 10 - tooltipcontent.value.offsetHeight; + // 设置箭头的样式 + arrow.value.style.borderLeft = '10px solid transparent'; + arrow.value.style.borderRight = '10px solid transparent'; + arrow.value.style.borderBottom = '10px solid transparent'; + arrow.value.style.borderTop = '10px solid cornflowerblue'; + arrow.value.style.top = `${tooltipcontent.value.offsetHeight}px`; + arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 5}px`; + break; + + case 'right': + // 设置tooltip 内容的样式 + position.left = 0; + position.top = 0; + position.left = slotElement.value.children[0].offsetLeft + slotElement.value.children[0].offsetWidth; + position.top = slotElement.value.children[0].offsetTop + slotElement.value.children[0].offsetHeight/2 - tooltipcontent.value.offsetHeight/2; + // 设置箭头的样式 + arrow.value.style.borderLeft = '10px solid transparent'; + arrow.value.style.borderRight = '10px solid cornflowerblue'; + arrow.value.style.borderBottom = '10px solid transparent'; + arrow.value.style.borderTop = '10px solid transparent'; + arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; + arrow.value.style.left = '-10px'; + break; + + case 'bottom': + // 设置tooltip的样式 + position.top = `${slotElement.value.children[0].offsetHeight + slotElement.value.children[0].offsetTop + 10}`; + position.left = `${slotElement.value.children[0].offsetLeft + slotElement.value.children[0].offsetWidth/2 - tooltipcontent.value.offsetWidth/2}`; + // 设置arrow.value的样式 + arrow.value.style.borderBottom = '10px solid orange'; + arrow.value.style.borderRight = '10px solid transparent'; + arrow.value.style.borderTop = '10px solid transparent'; + arrow.value.style.borderLeft = '10px solid transparent'; + arrow.value.style.top = `${-20}px`; + arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 10}px`; + break; + + case 'left': + position.top = `${slotElement.value.children[0].offsetTop + slotElement.value.children[0].offsetHeight/2 - tooltipcontent.value.offsetHeight/2}`; + position.left = `${slotElement.value.children[0].offsetLeft - 20 - tooltipcontent.value.offsetWidth}`; + // 设置arrow.value的样式 + arrow.value.style.borderLeft = '10px solid cornflowerblue'; + arrow.value.style.borderRight = '10px solid transparent'; + arrow.value.style.borderBottom = '10px solid transparent'; + arrow.value.style.borderTop = '10px solid transparent'; + arrow.value.style.left = `${tooltipcontent.value.offsetWidth + 10}px` + arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; + break; + + default: + console.error('The attribute position value is wrong, the value is one of top、right、left、bottom'); + break; + }; + + tooltip.value.style.top = position.top + 'px'; + tooltip.value.style.left = position.left + 'px'; + } else { + position.top = 0; + position.left = 0; + // 鼠标移走为false,隐藏提示框 + tooltip.value.style.opacity = '0'; + } + }); + + onBeforeUnmount (()=>{ + enterEvent.remove(); + leaveEvent.remove(); + }); + + return ()=>{ + const defaultSlot = renderSlot(useSlots(), 'default'); + return ( +
+
+ {defaultSlot} +
+
{/** tooltip 提示框 */} +
{/** tooltip 提示框箭头 */} +
{/** tooltip提示的内容 */} + {props.content} +
+
+
+ ) + } + } +}); \ No newline at end of file diff --git a/devui/tooltip/utils/EventListener.js b/devui/tooltip/utils/EventListener.js index 73f6f68c..724a31f6 100644 --- a/devui/tooltip/utils/EventListener.js +++ b/devui/tooltip/utils/EventListener.js @@ -1,5 +1,7 @@ const EventListener = { listen: function (target, eventType, callback) { + console.log('target:', target); + console.log('eventType:', eventType); if (target.addEventListener){ target.addEventListener(eventType, callback, false); return { diff --git a/sites/components/tabs/index.md b/sites/components/tabs/index.md index 1fe14767..f318f6d2 100644 --- a/sites/components/tabs/index.md +++ b/sites/components/tabs/index.md @@ -5,3 +5,4 @@ ### 何时使用 用户需要通过平级的区域将大块内容进行收纳和展现,保持界面整洁。 + diff --git a/sites/components/tooltip/index.md b/sites/components/tooltip/index.md index 8427c000..d055d230 100644 --- a/sites/components/tooltip/index.md +++ b/sites/components/tooltip/index.md @@ -1,4 +1,3 @@ - # Tooltip 提示 文字提示组件。 @@ -9,6 +8,14 @@ ### 基本用法 + + + + + + + + ```html
@@ -52,159 +59,5 @@ } ``` -```ts -export default defineComponent({ - name: 'DTooltip', - props: tooltipProps, - emits: [], - data (){ - return { - position: { - top: 0, - left: 0 - }, - show: false - } - }, - methods: { - // 延迟演示 默认100ms - delayShowTrue (fn, delay){ - let start; - if (parseInt(delay)>=0){ - return function (){ - if (start){ - clearTimeout(start); - } - start = setTimeout(fn, parseInt(delay)); - }; - } else{ - console.error('the value of delay is bigger than 0 and the type of delay must be string!'); - return - } - }, - // 延迟消失,默认150ms - delayShowFalse (fn, delay){ - if (this.show && parseInt(delay) >= 0){ - setTimeout(fn, parseInt(delay)); - } - } - }, - watch: { - show: function (newValue){ - if (newValue){ - // 鼠标悬浮为true,显示提示框 - this.$refs.tooltip.style.opacity = '1'; - const popover = this.$refs.tooltip; // 获取提示框组件 - const arrow = this.$refs.arrow; // 提示框组件箭头 - const triger = this.$refs.slotElement.children[0] // slot元素 - // 具体的判定规则 - switch (this.props.position){ - case 'top': - // 设置 tooltip 内容的样式 - this.position.left = triger.offsetLeft - popover.offsetWidth / 2 + triger.offsetWidth / 2; - this.position.top = `${triger.offsetTop - 10 - this.$refs.tooltipcontent.offsetHeight}`; - // 设置箭头的样式 - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid cornflowerblue'; - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight}px`; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 5}px`; - break; - - case 'right': - // 设置tooltip 内容的样式 - this.position.left = triger.offsetLeft + triger.offsetWidth; - this.position.top = triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2; - // 设置箭头的样式 - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.borderRight = '10px solid cornflowerblue'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; - arrow.style.left = '-10px'; - break; - - case 'bottom': - // 设置tooltip的样式 - this.position.top = `${triger.offsetHeight + triger.offsetTop + 10}`; - this.position.left = `${triger.offsetLeft + triger.offsetWidth/2 - this.$refs.tooltipcontent.offsetWidth/2}`; - // 设置arrow的样式 - arrow.style.borderBottom = '10px solid orange'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.borderLeft = '10px solid transparent'; - arrow.style.top = `${-20}px`; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth/2 - 10}px`; - break; - - case 'left': - this.position.top = `${triger.offsetTop + triger.offsetHeight/2 - this.$refs.tooltipcontent.offsetHeight/2}`; - this.position.left = `${triger.offsetLeft - 20 - this.$refs.tooltipcontent.offsetWidth}`; - // 设置arrow的样式 - arrow.style.borderLeft = '10px solid cornflowerblue'; - arrow.style.borderRight = '10px solid transparent'; - arrow.style.borderBottom = '10px solid transparent'; - arrow.style.borderTop = '10px solid transparent'; - arrow.style.left = `${this.$refs.tooltipcontent.offsetWidth + 10}px` - arrow.style.top = `${this.$refs.tooltipcontent.offsetHeight/2 - 10}px`; - break; - - default: - console.error('The attribute position value is wrong, the value is one of top、right、left、bottom'); - break; - }; - popover.style.top = this.position.top + 'px'; - popover.style.left = this.position.left + 'px'; - } else { - this.position.top = 0; - this.position.left = 0; - // 鼠标移走为false,隐藏提示框 - this.$refs.tooltip.style.opacity = '0'; - } - } - }, - mounted (){ - const self = this; - const slotEle = this.$refs.slotElement.children[0]; - // 初次渲染不显示 - if (!show){ - this.$refs.tooltip.style.opacity = '0'; - } - // 注册鼠标引入事件 - this.enterEvent = EventListener.listen(slotEle, 'mouseenter', self.delayShowTrue(function (){ - self.show = true; - }, self.mouseEnterDelay || 100)); - - // 注册鼠标移除事件 - this.leaveEvent = EventListener.listen(slotEle, 'mouseleave', self.delayShowFalse(function (){ - self.show = false; - },self.mouseLeaveDelay || 150)); - - }, - beforeUnmount (){ - this.enterEvent.remove(); - this.leaveEvent.remove(); - }, - render() { - const {} = this - - return ( -
-
- -
/** slot 元素 */ -
/** tooltip 提示框 */ -
/** tooltip 提示框箭头 */ -
- {{content}} -
/** tooltip提示的内容 */ -
-
- ); - } -}) -``` - ### 延时触发 -- Gitee From b6c78ef7df3d405fcb3eae4941b1e7bdb92a5287 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 17:41:40 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9position.top?= =?UTF-8?q?=E5=92=8Cposition.left=E5=80=BC=E7=9A=84=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index dda31c7d..5cae08b1 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -107,8 +107,8 @@ export default defineComponent({ case 'bottom': // 设置tooltip的样式 - position.top = `${slotElement.value.children[0].offsetHeight + slotElement.value.children[0].offsetTop + 10}`; - position.left = `${slotElement.value.children[0].offsetLeft + slotElement.value.children[0].offsetWidth/2 - tooltipcontent.value.offsetWidth/2}`; + position.top = slotElement.value.children[0].offsetHeight + slotElement.value.children[0].offsetTop + 10; + position.left = slotElement.value.children[0].offsetLeft + slotElement.value.children[0].offsetWidth/2 - tooltipcontent.value.offsetWidth/2; // 设置arrow.value的样式 arrow.value.style.borderBottom = '10px solid orange'; arrow.value.style.borderRight = '10px solid transparent'; @@ -119,8 +119,8 @@ export default defineComponent({ break; case 'left': - position.top = `${slotElement.value.children[0].offsetTop + slotElement.value.children[0].offsetHeight/2 - tooltipcontent.value.offsetHeight/2}`; - position.left = `${slotElement.value.children[0].offsetLeft - 20 - tooltipcontent.value.offsetWidth}`; + position.top = slotElement.value.children[0].offsetTop + slotElement.value.children[0].offsetHeight/2 - tooltipcontent.value.offsetHeight/2; + position.left = slotElement.value.children[0].offsetLeft - 20 - tooltipcontent.value.offsetWidth; // 设置arrow.value的样式 arrow.value.style.borderLeft = '10px solid cornflowerblue'; arrow.value.style.borderRight = '10px solid transparent'; -- Gitee From 3a0624236db4236f92e69a55fd4765f83c4269f5 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 17:51:00 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=BD=BF=E7=94=A8=E4=B8=8D=E5=BD=93?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E9=99=A4=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index 5cae08b1..de9e38d0 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -1,7 +1,7 @@ import './tooltip.scss' import { defineComponent, reactive, ref, watch, onMounted, getCurrentInstance, onBeforeUnmount, renderSlot, useSlots} from 'vue' -import { tooltipProps, TooltipProps } from './tooltip-types' +import { tooltipProps } from './tooltip-types' import EventListener from '../utils/EventListener' /** @@ -114,7 +114,7 @@ export default defineComponent({ arrow.value.style.borderRight = '10px solid transparent'; arrow.value.style.borderTop = '10px solid transparent'; arrow.value.style.borderLeft = '10px solid transparent'; - arrow.value.style.top = `${-20}px`; + arrow.value.style.top = '-20px'; arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 10}px`; break; -- Gitee From 54485d2dd65c46203dc36e46a23a7d21a5d22984 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 17:56:47 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index de9e38d0..625fada9 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -92,8 +92,6 @@ export default defineComponent({ case 'right': // 设置tooltip 内容的样式 - position.left = 0; - position.top = 0; position.left = slotElement.value.children[0].offsetLeft + slotElement.value.children[0].offsetWidth; position.top = slotElement.value.children[0].offsetTop + slotElement.value.children[0].offsetHeight/2 - tooltipcontent.value.offsetHeight/2; // 设置箭头的样式 -- Gitee From b1a2058bdc0839e659735f02ad45a3e395c02652 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 17:59:25 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip-types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devui/tooltip/src/tooltip-types.ts b/devui/tooltip/src/tooltip-types.ts index 0045bec5..0d203d2b 100644 --- a/devui/tooltip/src/tooltip-types.ts +++ b/devui/tooltip/src/tooltip-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { ExtractPropTypes } from 'vue' export type DevTooltip = 'top' | 'right' | 'bottom' | 'left'; export const DevTooltipShowAnimation = true; -- Gitee