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/9] =?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/9] =?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/9] =?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/9] =?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/9] =?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/9] =?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 From 1070a8de4fd6f169f3af0f339996ab11014d29e0 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Sun, 5 Sep 2021 18:38:17 +0800 Subject: [PATCH 7/9] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E7=AE=AD=E5=A4=B4?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.tsx | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index 625fada9..69cdb4ae 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -31,6 +31,10 @@ export default defineComponent({ let enterEvent; let leaveEvent; + const arrowStyle = (attr, value)=>{ + arrow.value.style[attr] = value; + }; + // 延迟显示 const delayShowTrue = function (fn, delay){ let start; @@ -75,6 +79,7 @@ export default defineComponent({ // 鼠标悬浮为true,显示提示框 tooltip.value.style.opacity = '1'; tooltip.value.style.zIndex = '500'; + arrow.value.style.border = '10px solid transparent'; // 具体的判定规则 switch (props.position){ case 'top': @@ -82,10 +87,7 @@ export default defineComponent({ 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'; + arrowStyle('borderTop', '10px solid cornflowerblue'); arrow.value.style.top = `${tooltipcontent.value.offsetHeight}px`; arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 5}px`; break; @@ -95,10 +97,7 @@ export default defineComponent({ 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'; + arrowStyle('borderRight', '10px solid cornflowerblue'); arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; arrow.value.style.left = '-10px'; break; @@ -108,10 +107,7 @@ export default defineComponent({ 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'; + arrowStyle('borderBottom', '10px solid cornflowerblue') arrow.value.style.top = '-20px'; arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 10}px`; break; @@ -120,10 +116,7 @@ export default defineComponent({ 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'; + arrowStyle('borderLeft', '10px solid cornflowerblue'); arrow.value.style.left = `${tooltipcontent.value.offsetWidth + 10}px` arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; break; -- Gitee From f9c2069beace14a9a5304ae97adc8e8cfd0bcc2b Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Tue, 7 Sep 2021 01:06:12 +0800 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AD=90=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E6=BA=A2=E5=87=BA=E9=9A=90=E8=97=8F=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=81=E5=AE=8C=E6=88=90tooltip=E6=89=80=E6=9C=89=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=81=E5=8E=BB=E6=8E=89=E5=88=86=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/tooltip/src/tooltip.scss | 2 +- devui/tooltip/src/tooltip.tsx | 142 ++++++++++++++------------- devui/tooltip/utils/EventListener.js | 2 - sites/components/tooltip/index.md | 89 +++++++++++------ 4 files changed, 132 insertions(+), 103 deletions(-) diff --git a/devui/tooltip/src/tooltip.scss b/devui/tooltip/src/tooltip.scss index 52dd4685..d123bbe2 100644 --- a/devui/tooltip/src/tooltip.scss +++ b/devui/tooltip/src/tooltip.scss @@ -1,6 +1,6 @@ .d-tooltip { box-sizing: border-box; - position: relative; + // position: relative; .tooltip { box-sizing: border-box; position: absolute; diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index 69cdb4ae..0f4231cd 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -1,5 +1,4 @@ import './tooltip.scss' - import { defineComponent, reactive, ref, watch, onMounted, getCurrentInstance, onBeforeUnmount, renderSlot, useSlots} from 'vue' import { tooltipProps } from './tooltip-types' import EventListener from '../utils/EventListener' @@ -16,133 +15,138 @@ export default defineComponent({ let position = reactive({ left: 0, top: 0 - }); - let show = ref(false); + }) + let show = ref(false) // slotElement元素的ref - let slotElement = ref(null); + let slotElement = ref(null) // tooltip元素的引用 - let tooltip = ref(null); + let tooltip = ref(null) // arrow元素的引用 - let arrow = ref(null); + let arrow = ref(null) // tooltipcontent的引用 - let tooltipcontent = ref(null); + let tooltipcontent = ref(null) - let enterEvent; - let leaveEvent; + let enterEvent + let leaveEvent const arrowStyle = (attr, value)=>{ - arrow.value.style[attr] = value; - }; + arrow.value.style[attr] = value + } // 延迟显示 - const delayShowTrue = function (fn, delay){ - let start; + const delayShowTrue = function (fn, delay=props.mouseEnterDelay){ + let start if (parseInt(delay)>=0){ return function (){ if (start){ - clearTimeout(start); + clearTimeout(start) } - start = setTimeout(fn, parseInt(delay)); - }; + start = setTimeout(fn, parseInt(delay)) + } } else{ - console.error('the value of delay is bigger than 0 and the type of delay must be string!'); + console.error('the value of delay is bigger than 0 and the type of delay must be string!') return } - }; + } // 延迟消失 - const delayShowFalse = function (fn, delay){ + const delayShowFalse = function (fn, delay=props.mouseLeaveDelay){ if (show.value && parseInt(delay) >= 0){ - setTimeout(fn, parseInt(delay)); + setTimeout(fn, parseInt(delay)) } - }; + } onMounted(()=>{ // 组件初始化不渲染tooltip if (!show.value){ - tooltip.value.style.opacity = '0'; - }; + tooltip.value.style.opacity = '0' + } // 注册鼠标引入事件 - enterEvent = EventListener.listen(slotElement.value.children[0], 'mouseenter', function (){ - show.value = true; - }); + /*enterEvent = EventListener.listen(slotElement.value.children[0], 'mouseenter', function (){ + show.value = true + })*/ + enterEvent = EventListener.listen(slotElement.value.children[0], 'mouseenter', delayShowTrue(function (){ + show.value = true + }, props.mouseEnterDelay)) // 注册鼠标移除事件 leaveEvent = EventListener.listen(slotElement.value.children[0], 'mouseleave', function (){ - show.value = false; - }); - }); + // show.value = false + setTimeout(function (){ + show.value = false; + }, props.mouseLeaveDelay) + }) + }) watch(show, function (newValue, oldValue){ if (newValue){ // 鼠标悬浮为true,显示提示框 - tooltip.value.style.opacity = '1'; - tooltip.value.style.zIndex = '500'; - arrow.value.style.border = '10px solid transparent'; + tooltip.value.style.opacity = '1' + tooltip.value.style.zIndex = '999' + arrow.value.style.border = '10px solid transparent' // 具体的判定规则 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; + 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 // 设置箭头的样式 - arrowStyle('borderTop', '10px solid cornflowerblue'); - arrow.value.style.top = `${tooltipcontent.value.offsetHeight}px`; - arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 5}px`; - break; + arrowStyle('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 = 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; + 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 // 设置箭头的样式 - arrowStyle('borderRight', '10px solid cornflowerblue'); - arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; - arrow.value.style.left = '-10px'; - break; + arrowStyle('borderRight', '10px solid cornflowerblue') + 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; + 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的样式 arrowStyle('borderBottom', '10px solid cornflowerblue') - arrow.value.style.top = '-20px'; - arrow.value.style.left = `${tooltipcontent.value.offsetWidth/2 - 10}px`; - break; + arrow.value.style.top = '-20px' + 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; + 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的样式 - arrowStyle('borderLeft', '10px solid cornflowerblue'); + arrowStyle('borderLeft', '10px solid cornflowerblue') arrow.value.style.left = `${tooltipcontent.value.offsetWidth + 10}px` - arrow.value.style.top = `${tooltipcontent.value.offsetHeight/2 - 10}px`; - break; + 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'; + 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; + position.top = 0 + position.left = 0 // 鼠标移走为false,隐藏提示框 - tooltip.value.style.opacity = '0'; + tooltip.value.style.opacity = '0' } - }); + }) onBeforeUnmount (()=>{ - enterEvent.remove(); - leaveEvent.remove(); - }); + enterEvent.remove() + leaveEvent.remove() + }) return ()=>{ - const defaultSlot = renderSlot(useSlots(), 'default'); + const defaultSlot = renderSlot(useSlots(), 'default') return (
@@ -158,4 +162,4 @@ export default defineComponent({ ) } } -}); \ No newline at end of file +}) \ No newline at end of file diff --git a/devui/tooltip/utils/EventListener.js b/devui/tooltip/utils/EventListener.js index 724a31f6..73f6f68c 100644 --- a/devui/tooltip/utils/EventListener.js +++ b/devui/tooltip/utils/EventListener.js @@ -1,7 +1,5 @@ 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/tooltip/index.md b/sites/components/tooltip/index.md index d055d230..770d55d4 100644 --- a/sites/components/tooltip/index.md +++ b/sites/components/tooltip/index.md @@ -8,6 +8,8 @@ ### 基本用法 +:::demo我们可以通过控制属性`position`来控制tooltip的显示位置,`position`取值有4个,分别是`top`、`right`、`bottom`、`left`。通过属性`content`控制tooltip提示框的内容。 + @@ -16,48 +18,73 @@ -```html -
- - +```vue + ``` -```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; - } - } +```css +.example { + height: 50px; + width: 60px; + background: cornflowerblue; + margin-top: 30px; } ``` +::: ### 延时触发 +鼠标移入的时长超过 [mouseEnterDelay] 毫秒之后才会触发,以防止用户无意划过导致的闪现,默认值是150毫秒;鼠标移出之后,再经过[mouseLeaveDelay]毫秒后,toolTip组件才会隐藏,默认值是100毫秒。 + +:::demo 通过`mouseEnterDelay`属性来控制tooltip提示框的`延迟显示`(默认是100ms),`mouseLeaveDelay`属性来控制tooltip提示框的`延迟消失`(默认是150ms) +
MouseEnter delay 500ms
+ +
MouseLeave delay 1000ms
+```vue + +``` + +```css +.customCss { + width: fit-content; + height: 30px; + padding: 10px; + display: flex; + justify-content: center; + align-items: center; + color: #fff; + background: cornflowerblue; +} +.customCss-leave { + width: fit-content; + height: 30px; + padding: 10px; + display: flex; + justify-content: center; + align-items: center; + color: #252b3a; + background: #fff; +} +``` +::: \ No newline at end of file -- Gitee From 84c0466a5feb4f4b5bca762e3f1e82b71439ed49 Mon Sep 17 00:00:00 2001 From: xiaojiujiu <3507440900@qq.com> Date: Thu, 9 Sep 2021 13:01:47 +0800 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= 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 | 2 +- devui/tooltip/src/tooltip-types.ts | 3 --- devui/tooltip/src/tooltip.scss | 1 - devui/tooltip/src/tooltip.tsx | 18 ++++++------------ sites/components/tooltip/index.md | 22 +++++++++++----------- 7 files changed, 18 insertions(+), 30 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 95881cad..3da2f803 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,3 @@ - module.exports = { parser: 'vue-eslint-parser', parserOptions: { diff --git a/devui/toast/src/toast.tsx b/devui/toast/src/toast.tsx index a056b7c4..5f925c36 100644 --- a/devui/toast/src/toast.tsx +++ b/devui/toast/src/toast.tsx @@ -1,4 +1,3 @@ - import './toast.scss' import { computed, defineComponent, nextTick, onUnmounted, ref, watch } from 'vue' diff --git a/devui/tooltip/index.ts b/devui/tooltip/index.ts index b5b67564..b5c96f4d 100644 --- a/devui/tooltip/index.ts +++ b/devui/tooltip/index.ts @@ -8,7 +8,7 @@ Tooltip.install = function(app: App) { export { Tooltip } export default { - title: 'Tooltip tooltip提示', + title: '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 index 0d203d2b..fc5fd184 100644 --- a/devui/tooltip/src/tooltip-types.ts +++ b/devui/tooltip/src/tooltip-types.ts @@ -4,9 +4,6 @@ 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' diff --git a/devui/tooltip/src/tooltip.scss b/devui/tooltip/src/tooltip.scss index d123bbe2..4b2186b1 100644 --- a/devui/tooltip/src/tooltip.scss +++ b/devui/tooltip/src/tooltip.scss @@ -1,6 +1,5 @@ .d-tooltip { box-sizing: border-box; - // position: relative; .tooltip { box-sizing: border-box; position: absolute; diff --git a/devui/tooltip/src/tooltip.tsx b/devui/tooltip/src/tooltip.tsx index 0f4231cd..b169d3cb 100644 --- a/devui/tooltip/src/tooltip.tsx +++ b/devui/tooltip/src/tooltip.tsx @@ -3,11 +3,6 @@ import { defineComponent, reactive, ref, watch, onMounted, getCurrentInstance, o import { tooltipProps } from './tooltip-types' import EventListener from '../utils/EventListener' -/** - * 使用: - * - * - */ export default defineComponent({ name: 'DTooltip', props: tooltipProps, @@ -72,9 +67,8 @@ export default defineComponent({ // 注册鼠标移除事件 leaveEvent = EventListener.listen(slotElement.value.children[0], 'mouseleave', function (){ - // show.value = false setTimeout(function (){ - show.value = false; + show.value = false }, props.mouseLeaveDelay) }) }) @@ -149,12 +143,12 @@ export default defineComponent({ const defaultSlot = renderSlot(useSlots(), 'default') return (
-
+
{defaultSlot} -
-
{/** tooltip 提示框 */} -
{/** tooltip 提示框箭头 */} -
{/** tooltip提示的内容 */} +
+
+
+
{props.content}
diff --git a/sites/components/tooltip/index.md b/sites/components/tooltip/index.md index 770d55d4..ee69846f 100644 --- a/sites/components/tooltip/index.md +++ b/sites/components/tooltip/index.md @@ -21,17 +21,17 @@ ```vue ``` -- Gitee