创建如图所示文件夹
index.jsx
import React, { useState, useEffect } from 'react';
import './index.css';
import Cover from './cover';
import { Tooltip, Button } from 'antd';
/**
* @param visible 显示/隐藏 指引
* @param title 引导提示内容
* @param placement 引导提示位置
* @param maxStep 引导步骤最大数
* @param currentStep 当前引导步数
* @param onComplete 点击完成的回调函数
* @param onPrevious 点击上一步的回调函数
* @param onNext 点击下一步的回调函数
*/
export default function index(props) {
const {
visible,
title,
placement,
maxStep,
currentStep,
onComplete,
onPrevious,
onNext
} = props;
return (
<>
<Tooltip
className="tip"
title={
<div className="tipBox">
<div>{title}</div>
{maxStep && (
<div className="tipContent">
{currentStep === 1 && (
<Button type="default" onClick={onNext}>
下一步
</Button>
)}
{currentStep === maxStep && (
<>
<Button
className="prev"
type="default"
onClick={onPrevious}
>
上一步
</Button>
<Button type="default" onClick={onComplete}>
完成
</Button>
</>
)}
{currentStep > 1 && currentStep < maxStep && (
<>
<Button
className="prev"
type="default"
onClick={onPrevious}
>
上一步
</Button>
<Button type="default" onClick={onNext}>
下一步
</Button>
</>
)}
</div>
)}
</div>
}
visible={visible}
placement={placement || 'right'}
>
<Cover />
<div className="content">{props.children}</div>
</Tooltip>
</>
);
}
index.css
.tip {
z-index: 9999999;
}
.content {
position: relative;
background: #fff;
display: inline-block;
z-index: 999999999;
/* 是否可选中内容 */
/* user-select: none; */
}
.ant-tooltip-inner {
max-width: 400px;
}
.tipContent {
display: flex;
justify-content: flex-end;
margin-top: 15px;
}
.tipContent button {
font-weight: bold;
}
.tipContent .prev {
margin-right: 10px;
}
cover/index.jsx
import React, { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import './index.css';
export default function index(props) {
const node = document.createElement('DIV');
useEffect(() => {
const body = document.body || document.documentElement;
body.appendChild(node);
return () => {
body.removeChild(node);
};
}, []);
return createPortal(<div className="view-cover"></div>, node);
}
cover/index.css
.view-cover {
height: 100%;
width: 100%;
background: rgba(0, 0, 0, 0.6);
position: fixed;
left: 0;
top: 0;
z-index: 999;
}
使用案例:
import React, { useState } from 'react';
import Intro from '../../components/Intro';
// 是否进入新人指引
const hasIntro =
JSON.parse(window.localStorage.getItem('intro')) === null ? true : false;
const maxStep = 3; // 当前页面 新人指引 最大步骤
export default function test() {
// curStep === 0 新手指引完成
const [curStep, setcurStep] = useState(1); // 当前引导步骤 -> 第一步
const next = () => {
setcurStep(curStep + 1);
};
const previous = () => {
setcurStep(curStep - 1);
};
const complete = () => {
window.localStorage.setItem('intro', false);
setcurStep(0); // 重置 0,新手指引完成
};
return (
<div>
{curStep == 1 && hasIntro ? (
<Intro
visible={curStep}
title={'test'}
currentStep={curStep}
maxStep={maxStep}
onNext={next}
>
<h1>PageA1</h1>
</Intro>
) : (
<h1>PageA1</h1>
)}
{curStep == 2 ? (
<Intro
visible={curStep}
title={'test'}
currentStep={curStep}
maxStep={maxStep}
onPrevious={previous}
onNext={next}
>
<h1>PageA2</h1>
</Intro>
) : (
<h1>PageA2</h1>
)}
{curStep == 3 ? (
<Intro
visible={curStep}
title={'test'}
currentStep={curStep}
maxStep={maxStep}
onPrevious={previous}
onComplete={complete}
>
<h1>PageA3</h1>
</Intro>
) : (
<h1>PageA3</h1>
)}
</div>
);
}