vue3eltour_0">vue3使用el-tour漫游式引导组件封装
我们这里先看下运行效果:
预览效果
引入的第三方库方法我这里就不写了,可以自行去官网查找。
我们看一下组件封装的部分。
vue_8">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-stepv-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 = stepemits('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-stepv-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
去做,详细的写法看上述代码即可
最后在父组件使用:
<TourPagev-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,},
]);