diff --git a/docs/en-US/component/tour.md b/docs/en-US/component/tour.md
index f27b0535dc..34459f9856 100644
--- a/docs/en-US/component/tour.md
+++ b/docs/en-US/component/tour.md
@@ -57,6 +57,16 @@ tour/indicator
:::
+## Target
+
+Various parameter passing types of target. The string and Function types are supported since ^(2.5.2).
+
+:::demo
+
+tour/target
+
+:::
+
## Tour API
:::tip
@@ -98,21 +108,21 @@ tour-step component configuration with the same name has higher priority
### TourStep Attributes
-| Property | Description | Type | Default |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
-| target | get the element the guide card points to. Empty makes it show in center of screen | `HTMLElement` | - |
-| show-arrow | whether to show the arrow | `boolean` | `true` |
-| title | title | `string` | - |
-| description | description | `string` | - |
-| placement | position of the guide card relative to the target element | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | `bottom` |
-| content-style | custom style for content | `CSSProperties` | - |
-| mask | whether to enable masking, change mask style and fill color by pass custom props | `boolean` \| ^[Object]`{ style?: CSSProperties; color?: string; }` | `true` |
-| type | type, affects the background color and text color | `default` \| `primary` | `default` |
-| next-button-props | properties of the Next button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - |
-| prev-button-props | properties of the previous button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - |
-| scroll-into-view-options | support pass custom scrollIntoView options, the default follows the `scrollIntoViewOptions` property of Tour | `boolean` \| `ScrollIntoViewOptions` | - |
-| show-close | whether to show a close button | `boolean` | `true` |
-| close-icon | custom close icon, default is Close | `string` \| `Component` | - |
+| Property | Description | Type | Default |
+| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
+| target | get the element the guide card points to. Empty makes it show in center of screen. the string and Function types are supported since ^(2.5.2). the string type is selectors of document.querySelector. | `HTMLElement` \| `string` \| ^[Function]`() => HTMLElement` | - |
+| show-arrow | whether to show the arrow | `boolean` | `true` |
+| title | title | `string` | - |
+| description | description | `string` | - |
+| placement | position of the guide card relative to the target element | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | `bottom` |
+| content-style | custom style for content | `CSSProperties` | - |
+| mask | whether to enable masking, change mask style and fill color by pass custom props | `boolean` \| ^[Object]`{ style?: CSSProperties; color?: string; }` | `true` |
+| type | type, affects the background color and text color | `default` \| `primary` | `default` |
+| next-button-props | properties of the Next button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - |
+| prev-button-props | properties of the previous button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - |
+| scroll-into-view-options | support pass custom scrollIntoView options, the default follows the `scrollIntoViewOptions` property of Tour | `boolean` \| `ScrollIntoViewOptions` | - |
+| show-close | whether to show a close button | `boolean` | `true` |
+| close-icon | custom close icon, default is Close | `string` \| `Component` | - |
### TourStep slots
diff --git a/docs/examples/tour/target.vue b/docs/examples/tour/target.vue
new file mode 100644
index 0000000000..402c7b3013
--- /dev/null
+++ b/docs/examples/tour/target.vue
@@ -0,0 +1,36 @@
+
+ Begin Tour
+
+
+
+
+ upload
+ save
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/components/tour/src/helper.ts b/packages/components/tour/src/helper.ts
index fe6d6464ea..583386b134 100644
--- a/packages/components/tour/src/helper.ts
+++ b/packages/components/tour/src/helper.ts
@@ -18,7 +18,14 @@ import {
offset as offsetMiddelware,
shift,
} from '@floating-ui/dom'
-import { hasOwn, isArray, isClient, keysOf } from '@element-plus/utils'
+import {
+ hasOwn,
+ isArray,
+ isClient,
+ isFunction,
+ isString,
+ keysOf,
+} from '@element-plus/utils'
import type {
CSSProperties,
@@ -40,7 +47,9 @@ import type {
} from '@floating-ui/dom'
export const useTarget = (
- target: Ref,
+ target: Ref<
+ string | HTMLElement | (() => HTMLElement | null) | null | undefined
+ >,
open: Ref,
gap: Ref,
mergedMask: Ref,
@@ -48,15 +57,28 @@ export const useTarget = (
) => {
const posInfo: Ref = ref(null)
+ const getTargetEl = () => {
+ let targetEl: HTMLElement | null | undefined
+ if (isString(target.value)) {
+ targetEl = document.querySelector(target.value)
+ } else if (isFunction(target.value)) {
+ targetEl = target.value()
+ } else {
+ targetEl = target.value
+ }
+ return targetEl
+ }
+
const updatePosInfo = () => {
- if (!target.value || !open.value) {
+ const targetEl = getTargetEl()
+ if (!targetEl || !open.value) {
posInfo.value = null
return
}
- if (!isInViewPort(target.value) && open.value) {
- target.value.scrollIntoView(scrollIntoViewOptions.value)
+ if (!isInViewPort(targetEl) && open.value) {
+ targetEl.scrollIntoView(scrollIntoViewOptions.value)
}
- const { left, top, width, height } = target.value.getBoundingClientRect()
+ const { left, top, width, height } = targetEl.getBoundingClientRect()
posInfo.value = {
left,
top,
@@ -104,8 +126,9 @@ export const useTarget = (
})
const triggerTarget = computed(() => {
- if (!mergedMask.value || !target.value || !window.DOMRect) {
- return target.value || undefined
+ const targetEl = getTargetEl()
+ if (!mergedMask.value || !targetEl || !window.DOMRect) {
+ return targetEl || undefined
}
return {
diff --git a/packages/components/tour/src/step.ts b/packages/components/tour/src/step.ts
index b683b0ddbc..9a48108cff 100644
--- a/packages/components/tour/src/step.ts
+++ b/packages/components/tour/src/step.ts
@@ -8,7 +8,9 @@ export const tourStepProps = buildProps({
* @description get the element the guide card points to. empty makes it show in center of screen
*/
target: {
- type: definePropType(Object),
+ type: definePropType<
+ string | HTMLElement | (() => HTMLElement | null) | null
+ >([String, Object, Function]),
},
/**
* @description the title of the tour content
diff --git a/packages/components/tour/src/types.ts b/packages/components/tour/src/types.ts
index ed219a92fe..cd8284d5d2 100644
--- a/packages/components/tour/src/types.ts
+++ b/packages/components/tour/src/types.ts
@@ -29,7 +29,7 @@ export interface PosInfo {
}
export interface UsedTourStepProps {
- target?: HTMLElement | null
+ target?: string | HTMLElement | (() => HTMLElement | null) | null
showArrow?: boolean
placement?: Placement
contentStyle?: CSSProperties