不使用第三方库怎么实现【前端引导页】功能?

简介: 不使用第三方库怎么实现【前端引导页】功能?

image.png


前言

随着应用功能越来越多,繁多而详细的功能使用和说明文档,已经不能满足时代追求 快速 的需求,而 引导页(或分步引导) 本质就是 化繁为简,将核心功能以更简单、简短、明了的文字指引用户去使用对应的功能,特别是 ToB 的项目,各种新功能需求迭代非常快,免不了需要 引导页 的功能来快速帮助用户引导。

下面我们通过两个方面来围绕着【前端引导页】进行展开:

  • 哪些第三方库可以直接使用快速实现功能?
  • 如何自己实现前端引导页的功能?

第三方库的选择

如果你不知道如何做技术选型,可以看看 山月大佬 的这一篇文章 在前端中,如何更好地做技术选型?,下面就简单列举几个相关的库进行简单介绍,具体需求具体分析选择,其他和 API 使用、具体实现效果可以通过官方文档或对应的 README.md 进行查看。

vue-tour

vue-tour 是一个轻量级、简单且可自定义的 Tour 插件,配置也算比较简单清晰,但只适用于 Vue2 的项目,具体效果可以直接参考对应的前面链接对应的内容。

image.png

driver.js

driver.js 是一个强大而轻量级的普通 JavaScript 引擎,可在整个页面上驱动用户的注意力,只有 4kb 左右的体积,并且没有外部依赖,不仅高度可定制,还可以支持所有主流浏览器。

image.png

shepherd.js

shepherd.js 包含的 API 众多,大多场景都可以通过其对应的配置得到,缺点就是整体的包体积较大,并且配置也比较复杂,配置复杂的内容一般都需要进行二次封装,将可变和不可变的配置项进行抽离,具体效果可见其 官方文档

image.png

intro.js

intro.js 是是一个开源的 vanilla Javascript/CSS 库,用于添加分步介绍或提示,大小在 10kB左右,属于轻量级的且无外部依赖,详情可见 官方文档

image.png

实现引导页功能

引导页核心功能其实就两点:

  • 一是 高亮部分
  • 二是 引导部分

而这两点其实真的不难实现,无非就是 引导部分 跟着 高亮部分 移动,并且添加一些简单的动画或过渡效果即可,也分为 蒙层引导无蒙层引导,这里介绍相对比较复杂的 蒙层引导,下面就简单介绍两种简单的实现方案。

cloneNode + position + transition

核心实现:

  • 高亮部分 通过 el.cloneNode(true) 复制对应目标元素节点,并将克隆节点添加到蒙层上
  • 通过 margin(或 tranlateposition 等)实现克隆节点的位置与目标节点重合
  • 引导部分 通过 position: fixed 实现定位效果,并通过动态修改 left、top 属性实现引导弹窗跟随目标移动
  • 过渡动画 通过 transition 实现位置的平滑移动
  • 页面 位置/内容 发生变化时(如:resize、scroll 事件),需要重新计算位置信息

缺点:

  • 目标节点需要被深度复制
  • 不能实现边引导边操作

效果演示:

image.png

核心代码:

// 核心配置参数
const selectors = [
  {
    selector: "#btn1",
    message: "点此【新增】数据!",
  },
  {
    selector: "#btn2",
    message: "小心【删除】数据!",
  },
  {
    selector: "#btn3",
    message: "可通过此按钮【修改】数据!",
  },
  {
    selector: "#btn4",
    message: "一键【完成】所有操作!",
  },
];
// Guide.vue
<script setup>
import { computed, onMounted, ref } from "vue";
const props = defineProps({
  selectors: Array,
});
const guideModalRef = ref(null);
const guideBoxRef = ref(null);
const index = ref(0);
const show = ref(true);
let cloneNode = null;
let currNode = null;
let message = computed(() => {
  return props.selectors[index.value]?.message;
});
const genGuide = (hasChange = true) => {
  // 前置操作
  cloneNode && guideModalRef.value?.removeChild(cloneNode);
  // 所有指引完毕
  if (index.value > props.selectors.length - 1) {
    show.value = false;
    return;
  }
  // 获取目标节点信息
  currNode =
    currNode || document.querySelector(props.selectors[index.value].selector);
  const { x, y, width, height } = currNode.getBoundingClientRect();
  // 克隆节点
  cloneNode = hasChange ? currNode.cloneNode(true) : cloneNode;
  cloneNode.id = currNode.id + "_clone";
  cloneNode.style = `
  margin-left: ${x}px;
  margin-top: ${y}px;
  `;
  // 指引相关
  if (guideBoxRef.value) {
    const halfClientHeight = guideBoxRef.value.clientHeight / 2;
    guideBoxRef.value.style = `
   left:${x + width + 10}px;
   top:${y <= halfClientHeight ? y : y - halfClientHeight + height / 2}px;
  `;
    guideModalRef.value?.appendChild(cloneNode);
  }
};
// 页面内容发生变化时,重新计算位置
window.addEventListener("resize", () => genGuide(false));
window.addEventListener("scroll", () => genGuide(false));
// 上一步/下一步
const changeStep = (isPre) => {
  isPre ? index.value-- : index.value++;
  currNode = null;
  genGuide();
};
onMounted(() => {
  genGuide();
});
</script>
<template>
  <teleport to="body">
    <div v-if="show" ref="guideModalRef" class="guide-modal">
      <div ref="guideBoxRef" class="guide-box">
        <div>{{ message }}</div>
        <button class="btn" :disabled="index === 0" @click="changeStep(true)">
          上一步
        </button>
        <button class="btn" @click="changeStep(false)">下一步</button>
      </div>
    </div>
  </teleport>
</template>
<style scoped>
.guide-modal {
  position: fixed;
  z-index: 999;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.3);
}
.guide-box {
  width: 150px;
  min-height: 10px;
  border-radius: 5px;
  background-color: #fff;
  position: absolute;
  transition: 0.5s;
  padding: 10px;
  text-align: center;
}
.btn {
  margin: 20px 5px 5px 5px;
}
</style>
复制代码

z-index + position + transition

核心实现:

  • 高亮部分 通过控制 z-index 的值,让目标元素展示在蒙层之上
  • 引导部分 通过 position: fixed 实现定位效果,并通过动态修改 left、top 属性实现引导弹窗跟随目标移动
  • 过渡动画 通过 transition 实现位置的平滑移动
  • 页面 位置/内容 发生变化时(如:resize、scroll 事件),需要重新计算位置信息

缺点:

  • 当目标元素的父元素 position: fixed | absolute | sticky 时,目标元素的 z-index 无法超过蒙版层(可参考 shepherd.jssvg 解决方案)

效果演示:

image.png

核心代码:

<script setup>
import { computed, onMounted, ref } from "vue";
const props = defineProps({
  selectors: Array,
});
const guideModalRef = ref(null);
const guideBoxRef = ref(null);
const index = ref(0);
const show = ref(true);
let preNode = null;
let message = computed(() => {
  return props.selectors[index.value]?.message;
});
const genGuide = (hasChange = true) => {
  // 所有指引完毕
  if (index.value > props.selectors.length - 1) {
    show.value = false;
    return;
  }
  // 修改上一个节点的 z-index
  if (preNode) preNode.style = `z-index: 0;`;
  // 获取目标节点信息
  const target =
    preNode = document.querySelector(props.selectors[index.value].selector);
  target.style = `
  position: relative; 
  z-index: 1000;
  `;
  const { x, y, width, height } = target.getBoundingClientRect();
  // 指引相关
  if (guideBoxRef.value) {
    const halfClientHeight = guideBoxRef.value.clientHeight / 2;
    guideBoxRef.value.style = `
   left:${x + width + 10}px;
   top:${y <= halfClientHeight ? y : y - halfClientHeight + height / 2}px;
  `;
  }
};
// 页面内容发生变化时,重新计算位置
window.addEventListener("resize", () => genGuide(false));
window.addEventListener("scroll", () => genGuide(false));
const changeStep = (isPre) => {
  isPre ? index.value-- : index.value++;
  genGuide();
};
onMounted(() => {
  genGuide();
});
</script>
<template>
  <teleport to="body">
    <div v-if="show" ref="guideModalRef" class="guide-modal">
      <div ref="guideBoxRef" class="guide-box">
        <div>{{ message }}</div>
        <button class="btn" :disabled="index === 0" @click="changeStep(true)">
          上一步
        </button>
        <button class="btn" @click="changeStep(false)">下一步</button>
      </div>
    </div>
  </teleport>
</template>
<style scoped>
.guide-modal {
  position: fixed;
  z-index: 999;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.3);
}
.guide-box {
  width: 150px;
  min-height: 10px;
  border-radius: 5px;
  background-color: #fff;
  position: absolute;
  transition: 0.5s;
  padding: 10px;
  text-align: center;
}
.btn {
  margin: 20px 5px 5px 5px;
}
</style>
复制代码

【扩展】SVG 如何完美解决 z-index 失效的问题?

这里以 shepherd.js 来举例说明,先来看起官方文档展示的 demo 效果:

image.png

在上述展示的效果中进行了一些验证:

  • 正常点击 NEXT 进入下一步指引,仔细观察 SVG 相关数据发生了变化
  • 等到指引部分指向代码块的内容区时,复制了此时 SVG 中和 path 相关的参数
  • 返回到第一步很明显此时的高亮部分高度较小,将上一步复制的参数直接替换当前 SVG 中和 path 相关的参数,此时发现整体 SVG 高亮内容宽高发生了变化

核心结论:通过 SVG 可编码的特点,利用 SVG 来实现蒙版效果,并且在绘制蒙版时,预留出目标元素的高亮区间(即 SVG 不需要绘制这一部分),这样就解决了使用 z-index 可能会失效的问题。

最后

欢迎关注同名公众号《熊的猫》,文章会同步更新!

以上就是一些简单实现,但还有很多细节需要考虑,比如:边引导边操作的实现、定位原因导致的图层展示问题等仍需要优化。

相信大部分人第一直觉是:直接使用第三方库实现功能就好了呀,自己实现功能不全、也未必好用,属实没有必要。

对于这一点其实在早前看到的一句话说的挺好:了解底层实现原理比使用库本身更有意义,当然每个人的想法不同,不过如果你想开始了解原理又不能立马挑战一些高深的内容,为什么不先从自己感兴趣的又不是那么复杂的功能开始呢?


目录
相关文章
|
7月前
|
存储 开发框架 前端开发
循序渐进VUE+Element 前端应用开发(18)--- 功能点管理及权限控制
循序渐进VUE+Element 前端应用开发(18)--- 功能点管理及权限控制
|
3月前
|
JSON 前端开发 搜索推荐
惊!这些前端技术竟然能让你的网站实现个性化推荐功能!
【10月更文挑战第30天】随着互联网技术的发展,个性化推荐已成为提升用户体验的重要手段。前端技术如JavaScript通过捕获用户行为数据、实时更新推荐结果等方式,在实现个性化推荐中扮演关键角色。本文将深入解析这些技术,并通过示例代码展示其实际应用。
131 4
|
4月前
|
前端开发 JavaScript
前端中的“+”连接符,居然有鲜为人知的强大功能!
【10月更文挑战第9天】前端中的“+”连接符,居然有鲜为人知的强大功能!
67 0
前端中的“+”连接符,居然有鲜为人知的强大功能!
|
5月前
|
前端开发 API
(WEB前端编辑DWG)在线CAD如何实现图形识别功能
mxcad 提供的图形识别功能可帮助用户快速识别和提取 CAD 图纸中的各种图形,如直线、多段线、弧线、圆及图块,显著提升设计效率。此功能不仅适用于图形分类,还能进行数量统计和快速定位,减少手动操作。用户可通过 API 进行二次开发,自定义识别逻辑。具体步骤包括打开在线示例、选择识别功能、设置识别参数并开始识别。更多开发文档请关注公众号:梦想云图网页 CAD。
|
4月前
|
Web App开发 存储 前端开发
前端开发必备:requestAnimationFrame、setInterval、setTimeout——功能解析与优劣对比
前端开发必备:requestAnimationFrame、setInterval、setTimeout——功能解析与优劣对比
237 0
|
4月前
|
移动开发 前端开发 JavaScript
前端开发实战:利用Web Speech API之speechSynthesis实现文字转语音功能
前端开发实战:利用Web Speech API之speechSynthesis实现文字转语音功能
540 0
|
5月前
|
存储 JSON 前端开发
node使用token来实现前端验证码和登录功能详细流程[供参考]=‘很值得‘
本文介绍了在Node.js中使用token实现前端验证码和登录功能的详细流程,包括生成验证码、账号密码验证以及token验证和过期处理。
120 0
node使用token来实现前端验证码和登录功能详细流程[供参考]=‘很值得‘
|
4月前
|
前端开发 JavaScript Shell
深入解析前端构建利器:webpack核心概念与基本功能全览
深入解析前端构建利器:webpack核心概念与基本功能全览—
54 0
|
5月前
|
前端开发 开发者
在前端开发中,webpack 作为一个强大的模块打包工具,为我们提供了丰富的功能和扩展性
【9月更文挑战第1天】在前端开发中,Webpack 作为强大的模块打包工具,提供了丰富的功能和扩展性。本文重点介绍 DefinePlugin 插件,详细探讨其原理、功能及实际应用。DefinePlugin 可在编译过程中动态定义全局变量,适用于环境变量配置、动态加载资源、接口地址配置等场景,有助于提升代码质量和开发效率。通过具体配置示例和注意事项,帮助开发者更好地利用此插件优化项目。
104 13
|
6月前
|
开发框架 移动开发 前端开发
基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍
基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

热门文章

最新文章

  • 1
    【Java若依框架】RuoYi-Vue的前端和后端配置步骤和启动步骤
  • 2
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 4
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 5
    详解智能编码在前端研发的创新应用
  • 6
    巧用通义灵码,提升前端研发效率
  • 7
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 8
    智能编码在前端研发的创新应用
  • 9
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 10
    抛弃node和vscode,如何用记事本开发出一个完整的vue前端项目
  • 1
    以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
    24
  • 2
    大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
    43
  • 3
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    25
  • 4
    巧用通义灵码,提升前端研发效率
    84
  • 5
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    137
  • 6
    详解智能编码在前端研发的创新应用
    92
  • 7
    智能编码在前端研发的创新应用
    75
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    35
  • 9
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    111
  • 10
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    73