diff --git a/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts b/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts
index 97ad474077..d473804fae 100644
--- a/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts
+++ b/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts
@@ -1,6 +1,4 @@
import { mount } from '@vue/test-utils';
-import { ReadTip, } from '../index';
-import { nextTick } from 'vue';
import TipsTemplate from '../src/read-tip-template';
@@ -27,15 +25,15 @@ describe('read-tip test', () => {
title: 'Name: Jack',
content: 'This is Jack\'s profile',
};
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
}
});
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.title);
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).toContain(defaultTemplateProps.title);
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.content);
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).toContain(defaultTemplateProps.content);
});
@@ -53,13 +51,14 @@ describe('read-tip test', () => {
title: 'Name: Jack',
content: 'This is Jack\'s profile',
};
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
}
});
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('read-tip-container ' + defaultTemplateProps.position);
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML)
+ .toContain('read-tip-container ' + defaultTemplateProps.position);
});
});
@@ -74,17 +73,17 @@ describe('read-tip test', () => {
title: 'Name: Jack',
content: 'This is Jack\'s profile',
};
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
}
});
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toBe('');
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).toBe('');
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.title);
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).not.toContain(defaultTemplateProps.title);
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.content);
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).not.toContain(defaultTemplateProps.content);
});
@@ -98,7 +97,7 @@ describe('read-tip test', () => {
selector: '#readtip-target',
contentTemplate: true
};
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
},
@@ -107,24 +106,23 @@ describe('read-tip test', () => {
}
});
- expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('
I am test
');
+ expect(document.querySelector(defaultTemplateProps.selector)?.innerHTML).toContain(' I am test
');
});
it('read-tip dataFn', async () => {
// 基础用法
-
+ function getDataFromDB({ element, rule }) {
+ return { content: element.innerHTML, title: rule.key };
+ }
const defaultTemplateProps = {
appendToBody: false,
selector: '#readtip-target',
dataFn: getDataFromDB,
key: 'GetData'
};
- function getDataFromDB({ element, rule }) {
- return { content: element.innerHTML, title: rule.key };
- }
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
},
@@ -135,6 +133,9 @@ describe('read-tip test', () => {
});
it('read-tip overlayClassName', async () => {
+ function getDataFromDB({ element, rule }) {
+ return { content: element.innerHTML, title: rule.key };
+ }
// 基础用法
const defaultTemplateProps = {
appendToBody: false,
@@ -143,10 +144,7 @@ describe('read-tip test', () => {
key: 'GetData',
overlayClassName: 'red'
};
- function getDataFromDB({ element, rule }) {
- return { content: element.innerHTML, title: rule.key };
- }
- const wrapper = mount(TipsTemplate, {
+ mount(TipsTemplate, {
props: {
defaultTemplateProps
},
diff --git a/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx b/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx
index 185dbc0d59..3060bc8b4c 100644
--- a/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx
+++ b/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx
@@ -1,3 +1,4 @@
+import type { CSSProperties } from 'vue';
import { defineComponent, reactive, ref, onMounted, Teleport, toRefs } from 'vue';
import { readTipProps, ReadTipProps, DefaultTemplateProps } from './read-tip-types';
import './read-tip.scss';
@@ -11,7 +12,7 @@ export default defineComponent({
let rule: DefaultTemplateProps = defaultTemplateProps.value;
const query = rule?.id ? `#${rule.id}` : rule.selector;
- const styles: any = reactive({});
+ const styles: CSSProperties = reactive({});
if (typeof rule.dataFn === 'function') {
const dataFn = rule.dataFn({ element: document.querySelector(query), rule });
rule = { ...rule, ...dataFn };
@@ -27,7 +28,7 @@ export default defineComponent({
return deviationConstant;
};
onMounted(() => {
- const domBounding = document.querySelector(query).getBoundingClientRect();
+ const domBounding = document.querySelector(query)?.getBoundingClientRect();
const { width, height } = domBounding;
const distance = 10;
let positionTop = 0;
@@ -38,7 +39,7 @@ export default defineComponent({
let positionLeft = 0;
- const targetDom = document.querySelector('.read-tip-container').getBoundingClientRect();
+ const targetDom = document.querySelector('.read-tip-container')?.getBoundingClientRect();
if (rule.appendToBody) {
positionTop = domBounding.y + document.documentElement.scrollTop;
positionLeft = domBounding.x;
@@ -72,7 +73,7 @@ export default defineComponent({
>
{
- rule.contentTemplate ? ctx.slots?.default() :
+ rule.contentTemplate ? ctx.slots?.default?.() :
(
<>
diff --git a/packages/devui-vue/devui/read-tip/src/read-tip-types.ts b/packages/devui-vue/devui/read-tip/src/read-tip-types.ts
index c9171aab4a..c1f8e6e2e4 100644
--- a/packages/devui-vue/devui/read-tip/src/read-tip-types.ts
+++ b/packages/devui-vue/devui/read-tip/src/read-tip-types.ts
@@ -1,17 +1,31 @@
import type { PropType, ExtractPropTypes } from 'vue';
-export const readTipProps = {
- readTipOptions: {
- type: Object as PropType
- },
- defaultTemplateProps: {
- type: Object as PropType
- }
-} as const;
-
export type Position = 'top' | 'left' | 'right' | 'bottom';
export type Trigger = 'hover' | 'click';
+export interface ReadTipRule {
+ id?: string;
+ key?: string;
+ selector: string | null;
+ trigger?: Trigger;
+ title?: string;
+ content?: string;
+ showAnimate?: boolean;
+ mouseenterTime?: number;
+ mouseleaveTime?: number;
+ position?: Position;
+ overlayClassName?: string;
+ appendToBody?: boolean;
+ status?: boolean;
+ // customData与template搭配使用,customData为传入模板的上下文,可以自定义模板内容
+ dataFn?: ({
+ element,
+ rule: ReadTipRule,
+ }) => { title?: string; content?: string };
+}
+
+export type ReadTipRules = ReadTipRule | ReadTipRule[];
+
export type DefaultTemplateProps = {
title?: string;
content?: string;
@@ -41,26 +55,13 @@ export interface ReadTipOptions {
}
-export type ReadTipRules = ReadTipRule | ReadTipRule[];
-
-export interface ReadTipRule {
- key?: string;
- selector: string;
- trigger?: Trigger;
- title?: string;
- content?: string;
- showAnimate?: boolean;
- mouseenterTime?: number;
- mouseleaveTime?: number;
- position?: Position;
- overlayClassName?: string;
- appendToBody?: boolean;
- // customData与template搭配使用,customData为传入模板的上下文,可以自定义模板内容
- dataFn?: ({
- element,
- rule: ReadTipRule,
- }) => { title?: string; content?: string };
-}
-
+export const readTipProps = {
+ readTipOptions: {
+ type: Object as PropType
+ },
+ defaultTemplateProps: {
+ type: Object as PropType
+ }
+} as const;
export type ReadTipProps = ExtractPropTypes;
diff --git a/packages/devui-vue/devui/read-tip/src/read-tip.tsx b/packages/devui-vue/devui/read-tip/src/read-tip.tsx
index 08305403e4..bbdee8f2a2 100644
--- a/packages/devui-vue/devui/read-tip/src/read-tip.tsx
+++ b/packages/devui-vue/devui/read-tip/src/read-tip.tsx
@@ -1,8 +1,22 @@
import { defineComponent, ref, onMounted, reactive, onUnmounted } from 'vue';
-import { readTipProps, ReadTipProps, ReadTipOptions } from './read-tip-types';
+import { readTipProps } from './read-tip-types';
+import type { ReadTipProps, ReadTipOptions, ReadTipRules, ReadTipRule } from './read-tip-types';
import './read-tip.scss';
import TipsTemplate from './read-tip-template';
+// 把传入的props.rules统一转为数组对象格式
+const rules = (ruleList: ReadTipRules) => {
+ if (ruleList === null) { return []; }
+ if (typeof ruleList === 'object' && !Array.isArray(ruleList)) {
+ ruleList = [ruleList];
+ }
+ ruleList = [...ruleList];
+ Array.isArray(ruleList) && ruleList.map(rule => {
+ rule.status = false;
+ });
+ return ruleList;
+};
+
export default defineComponent({
name: 'DReadTip',
props: readTipProps,
@@ -21,8 +35,9 @@ export default defineComponent({
};
// 合并基础配置
const options = { ...defaultOptions, ...props.readTipOptions };
- const defaultSlot = ref(null);
- const onMouseenter = (rule) => () => {
+ const defaultSlot = ref(null);
+ const refRules = reactive(rules(options.rules));
+ const onMouseenter = (rule: ReadTipRule) => () => {
setTimeout(() => {
if (rule.id) {
const a = refRules.find(u => u.id === rule.id);
@@ -31,7 +46,7 @@ export default defineComponent({
rule.status = true;
}, rule.mouseenterTime || options.mouseenterTime);
};
- const onMouseleave = (rule) => () => {
+ const onMouseleave = (rule: ReadTipRule) => () => {
setTimeout(() => {
if (rule.id) {
const a = refRules.find(u => u.id === rule.id);
@@ -42,17 +57,17 @@ export default defineComponent({
}, rule.mouseleaveTime || options.mouseleaveTime);
};
- const init = (rules, trigger = 'hover') => {
- rules.map(rule => {
+ const init = (ruleList, trigger = 'hover') => {
+ ruleList.map(rule => {
rule.status = false;
trigger = rule.trigger || trigger;
rule.overlayClassName = rule.overlayClassName || options.overlayClassName;
rule.position = rule.position || options.position;
rule.contentTemplate = !!(ctx.slots.contentTemplate);
- if (!('appendToBody' in rule)) {rule.appendToBody = options.appendToBody;}
- const doms = defaultSlot.value.querySelectorAll(rule.selector);
+ if (!('appendToBody' in rule)) { rule.appendToBody = options.appendToBody; }
+ const doms = defaultSlot.value?.querySelectorAll(rule.selector);
[...doms].map((dom, index) => {
- if (rule.appendToBody === false) {dom.style.position = 'relative';}
+ if (rule.appendToBody === false) { dom.style.position = 'relative'; }
let newRule = reactive({
id: null
});
@@ -61,34 +76,20 @@ export default defineComponent({
newRule = { ...rule };
dom.id = id;
newRule.id = id;
- rules.push(newRule);
+ ruleList.push(newRule);
}
-
if (trigger === 'hover') {
dom.addEventListener('mouseenter', onMouseenter(newRule.id ? newRule : rule,));
dom.addEventListener('mouseleave', onMouseleave(newRule.id ? newRule : rule));
}
});
-
});
- return rules;
+ return ruleList;
};
- function show(dom, rule) {
+ function show(_: unknown, rule) {
rule.status = true;
}
- // 把传入的props.rules统一转为数组对象格式
- const rules = (rules) => {
- if (rules === null) {return;}
- if (typeof rules === 'object' && !Array.isArray(rules)) {
- rules = [rules];
- }
- rules = [...rules];
- Array.isArray(rules) && rules.map(rule => {
- rule.status = false;
- });
- return rules;
- };
- const refRules = reactive(rules(options.rules));
+
const clickFn = () => {
refRules.forEach(element => {
element.status = false;
@@ -109,56 +110,42 @@ export default defineComponent({
// 添加点击事件 当前元素是click事件目标则弹框展示
const onClick = (e: Event) => {
for (const rule of refRules) {
- const doms = defaultSlot.value.querySelectorAll(rule.selector);
+ const doms = defaultSlot.value?.querySelectorAll(rule.selector);
for (const dom of doms) {
if (doms.length > 1) {
if (dom === e.target && rule.id) {
show(dom, rule);
return;
-
} else if (dom === e.target && !rule.id && !dom.id) {
show(dom, rule);
return;
}
-
- } else
-
- if (dom === e.target) {
+ } else if (dom === e.target) {
show(dom, rule);
return;
} else {
rule.status = false;
}
}
-
}
-
};
return () => {
return (
-
- {
- ctx.slots?.default()
- }
+
+ {ctx.slots?.default?.()}
-
{(refRules).map(rule => (
-
- {rule.status && (
- {
- rule.contentTemplate && ctx.slots?.contentTemplate()
- }
- )
-
- }
+
+ {rule.status && (
+
+ {
+ rule.contentTemplate && ctx.slots?.contentTemplate?.()
+ }
+
+ )}
- )
- )}
+ ))}
);
};