当前位置: 首页 > article >正文

vue3封装el-tour漫游式引导

vue3使用el-tour漫游式引导组件封装

我们这里先看下运行效果:

预览效果

引入的第三方库方法我这里就不写了,可以自行去官网查找。
我们看一下组件封装的部分。

tourPage.vue
  <el-tour v-model="open" :show-close="false" @change="onStepChange" :content-style="{
      width: '80%',
      fontSize: '16px',
      color: '#252525',
    }">
      <el-tour-step v-for="(item, index) in data" :key="index" :target="item.target" :title="item.title ? item.title : `第${currentStep}步`" :description="item.description" :prev-button-props="{
        children: '上一步',
        onClick: handlePrevClick
      }" :next-button-props="{
        children: nextBtnName,
        onClick: handleNextClick
      }" />
      <template #indicators="{ current, total }">
        <span style="font-size: 16px; color: #252525;">{{ current + 1 }} / {{ total }}</span>
      </template>
    <!--   <template #indicators>
        <el-button size="small" @click="handleSkip">跳过</el-button>
      </template> -->
    </el-tour>

数据结构:

const tourData = computed(() => [
  {
    title: "功能引导",
    description: "让我们来学习一下",
  },
  {
    title: "功能按钮",
    description: "这里有每日一言和票房大全功能入口",
    target: () => ref1.value,
  },
  {
    title: "个人中心",
    description: "点击头像可以打开个人中心,更换头像和昵称,还可以和机器人对话",
    target: () => ref2.value,
  },
  {
    title: "新年彩蛋",
    description: "一会可以点击这里,看看有什么惊喜",
    target: () => ref3.value,
  },
  {
    title: "关于文案",
    description: "表面可以查看文案,从这里点击进入可以开启音乐",
    target: () => ref4?.value?.$el || null
  },
  {
    title: "抽奖",
    description: "点击这里可以进入抽奖页面,试试手气吧",
    target: () => ref5.value,
  },
]);

这里需要注意一下第四个部分,我这里因为要直接绑定第三方组件Vant的van-notice-bar的所以需要使用Vant中自带的NoticeBarInstance 类型

import type { NoticeBarInstance } from 'vant';

所以在定义的时候需要这么写

const ref4 = ref<NoticeBarInstance>()          // 文案通知栏
// 数据
target: () => ref4?.value?.$el || null

如果是引导饿了么的组件获取dom类型可以从官网上查看,比如绑定在el-button按钮上

import type { ButtonInstance } from 'element-plus'
const ref4 = ref<ButtonInstance>()   
// 数据
{
    title: "关于文案",
    description: "表面可以查看文案,从这里点击进入可以开启音乐",
    target: () => ref4?.value?.$el || null
},

如果不用官网的方法也可以直接使用js方法获取,当然你也不需要NoticeBarInstance 类型了

const ref4 = ref<HTMLElement | null>(null)
// 数据
{
    title: "关于文案",
    description: "表面可以查看文案,从这里点击进入可以开启音乐",
    target: () => document.querySelector('.van-notice-bar'),
},

自定义按钮文字
在这里插入图片描述

      <el-tour-step
        v-for="(item, index) in data"
        :key="index"
        :target="item.target"
        :title="item.title ? item.title : `第${currentStep}步`"
        :description="item.description"
        :prev-button-props="{
          children: '上一步',
          onClick: handlePrevClick
        }"
        :next-button-props="{
          children: nextBtnName,
          onClick: handleNextClick
        }"
      />

组件完整代码:

<script setup lang="ts">
import { ref, computed, PropType } from "vue";
import type { ButtonInstance } from 'element-plus'
import type { NoticeBarInstance } from 'vant';
// 引导步骤项目接口定义
interface TourItem {
  title: string;                   // 步骤标题
  description: string;             // 步骤描述
  target?: () => NoticeBarInstance | HTMLElement | null | undefined | any;  // 目标元素
}
// Props 定义
const props = defineProps({
  data: {
    type: Array as PropType<TourItem[]>,
    required: true
  },
  modelValue: {
    type: Boolean,
    default: false
  }
})

// 事件发射器
const emits = defineEmits(['change', 'prev', 'next', 'update:modelValue'])

// 引导组件显示状态(双向绑定)
const open = computed({
  get: () => props.modelValue,
  set: (value) => emits('update:modelValue', value)
})

// 当前引导步骤
const currentStep = ref(0);

// 下一步按钮文本
const nextBtnName = computed(() => {
  let name = ''
  if (!currentStep.value) {
    name = '开始'
  } else if (currentStep.value === props.data.length - 1) {
    name = '完成'
  } else {
    name = `下一步(${currentStep.value} / ${props.data.length - 1}`
  }
  return name
})

// 步骤变化处理函数
const onStepChange = (step: number) => {
  currentStep.value = step
  emits('change', step)
}

// 跳过按钮处理函数(暂未启用)
/* const handleSkip = () => {
  open.value = false
} */

// 上一步按钮处理函数
const handlePrevClick = () => {
  emits('prev', currentStep.value)
}

// 下一步按钮处理函数
const handleNextClick = () => {
  emits('next', currentStep.value)
}
</script>

<template>
  <div>
    <el-tour v-model="open" :show-close="false" @change="onStepChange" :content-style="{
      width: '80%',
      fontSize: '16px',
      color: '#252525',
    }">
      <el-tour-step
        v-for="(item, index) in data"
        :key="index"
        :target="item.target"
        :title="item.title ? item.title : `第${currentStep}步`"
        :description="item.description"
        :prev-button-props="{
          children: '上一步',
          onClick: handlePrevClick
        }"
        :next-button-props="{
          children: nextBtnName,
          onClick: handleNextClick
        }"
      />
      <template #indicators="{ current, total }">
        <span style="font-size: 16px; color: #252525;">{{ current + 1 }} / {{ total }}</span>
      </template>
      <!-- 跳过按钮(暂未启用) -->
      <!-- <template #indicators>
        <el-button size="small" @click="handleSkip">跳过</el-button>
      </template> -->
    </el-tour>
  </div>
</template>

<style scoped></style>

这里的记步条可以用插槽indicators去做,详细的写法看上述代码即可
最后在父组件使用:

    <TourPage
      v-model="tourVisible"
      :data="tourData"
      @change="(step) => console.log('当前步骤:', step)"
      @prev="(step) => console.log('上一步:', step)"
      @next="(step) => console.log('下一步:', step)"
    />
    <el-button color="#626aef" @click="startTour">
      快速引导
    </el-button>
const tourVisible = ref(false)
// 点击时开启
const startTour = () => {
  tourVisible.value = true
}

数据附下

// 引导步骤配置
const tourData = computed(() => [
  {
    title: "功能引导",
    description: "让我们来学习一下",
  },
  {
    title: "功能按钮",
    description: "这里有每日一言和票房大全功能入口",
    target: () => ref1.value,
  },
  {
    title: "个人中心",
    description: "点击头像可以打开个人中心,更换头像和昵称,还可以和机器人对话",
    target: () => ref2.value,
  },
  {
    title: "新年彩蛋",
    description: "一会可以点击这里,看看有什么惊喜",
    target: () => ref3.value,
  },
  {
    title: "关于文案",
    description: "表面可以查看文案,从这里点击进入可以开启音乐",
    target: () => ref4?.value?.$el || null
  },
  {
    title: "抽奖",
    description: "点击这里可以进入抽奖页面,试试手气吧",
    target: () => ref5.value,
  },
]);

http://www.kler.cn/a/505449.html

相关文章:

  • 我这不需要保留本地修改, 只需要拉取远程更改
  • TCP 连接状态标识 | SYN, FIN, ACK, PSH, RST, URG
  • springboot程序快速入门
  • 灵活妙想学数学
  • 深入了解生成对抗网络(GAN):原理、实现及应用
  • Git的基本命令以及其原理(公司小白学习)
  • 09.VSCODE:安装 Git for Windows
  • .NetCore 使用 NPOI 读取带有图片的excel数据
  • 软件测试 —— Selenium(等待)
  • 物联网云平台:智能硬件芯片 esp32 的开放式管理设计
  • 【Elasticsearch复合查询】
  • 基于spingboot+html技术的博客网站
  • 1.1.1 C语言常用的一些函数(持续更新)
  • 最好用的图文识别OCR -- PaddleOCR(4) 模型微调
  • 【JVM中的三色标记法是什么?】
  • ssh, git 配置多对公私钥
  • 简识MySQL中ReadView、RC、RR的关系
  • 二级缓存(缓存到Redis)
  • Electron 开发者的 Tauri 2.0 实战指南:文件系统操作
  • LeetCode热题100(三十四) —— 23.合并K个升序链表
  • git报错处理
  • linux服务器 常用脚本(超全)
  • SpringBoot项目中解决CORS跨域资源共享问题
  • 比较分析:Windsurf、Cody、Cline、Roo Cline、Copilot 和 通义灵码
  • hadoop3.3和hive4.0安装——单节点
  • ubuntu如何搭建ftp