跨页面跳转 卡点问题:
vue-tour跨页面引导时,会因为页面未加载完成=>获取不到下个步骤的dom,导致下个步骤无法被框选。
目标效果:
1.点击下一步时,自动点击相应按钮打开弹窗或跳转页面等
2.点击跳转页面时,等页面加载完毕才显示该步骤引导的UI
先附上vue-tour官方文档:github.com/pulsardev/v…
主要流程
- 安装vue-tour并在main.js中引入
↓
- 在需要添加引导的所有组件的共同父组件中,配置v-tour
在vue中,所有组件的父组件一定有的是App.vue,官方默认也是写在App.vue;但如果写了layout等模板,在layout里配置也未尝不可,只要该父组件包含了要添加引导的所有页面子组件即可。
以下是v-tour的配置项:
- steps(步骤对应的dom、显示文字和before UI步进函数)
- options(包含按钮名称、是否高亮、是否打开debug等配置)
- callbacks(回调函数,允许您在漫游的不同时刻执行自定义操作)
↓
- 在第一步骤的组件完成渲染的时候,this.$tours['myTour'].start()开始漫游
跨页面跳转 解决流程
每个步骤都可以配置一个before函数,函数在该步骤的UI渲染之前调用,返回一个promise。
- 「父组件」:在步骤的before函数中,判断该步骤对应的DOM是否已存在,若不存在则 a.等待/跳转等 b.记录该操作 c.不resolve(即拦截了此次展示该步骤引导UI);若存在则resolve。
↓
- 「跳转后的子组件」:在步骤DOM渲染结束之后(比如mounted、数据接口调用结束后等),通知父组件。
↓
- 「父组件」:接到通知,根据记录的操作再次走上一步/下一步。此时before函数判断步骤的DOM已存在,成功展示步骤引导UI。
1. 安装vue-tour并在main.js中引入
npm install vue-tour
在main.js中引入
//main.js
import VueTour from 'vue-tour'
require('vue-tour/dist/vue-tour.css')
Vue.use(VueTour)
2. 在需要添加引导的所有组件的共同父组件中,配置v-tour
若需要自定义样式,请参考官方文档 Customizing the Template (如果用到了highlight,需要将highlight属性传递给v-step的props哦!)
以下使用默认样式演示:
//父组件 layout.vue / App.vue / ……
<template>
<div>
<!-- 记得绑定监听子组件事件 -->
<router-view @domDone="domDone"></router-view>
<v-tour name="myTour" :steps="steps" :options="myOptions" :callbacks="myCallbacks"></v-tour>
</div>
</template>
<script>
export default {
data() {
return {
steps: [
{
target: '#v-step-1',
content: `第一步:点击 <strong>XXXXX</strong> !`,
//如需点击上一步,请配置
before: type => new Promise((resolve, reject) => {
//判断如果要展示第一步UI的时候,尚未跳转至第一步页面,则跳转
if (this.$route.path !== '/first-page') {
//标识正在操作步骤的类型
this.pendingStatus = type;
//跳转页面
this.$router.push('/first-step-page')
}
//如果已跳转至第一步页面,则成功展示第一步
else if (this.$route.path === '/first-step-page') {
resolve('foo')
}
})
},
{
target: '#v-step-2',
content: '第二步:XXXXX',
before: type => new Promise((resolve, reject) => {
//判断如果要展示第二步UI的时候,尚未跳转至第二步页面,则跳转
if (this.$route.name !== 'second-step-page') {
//标识正在操作步骤的类型
this.pendingStatus= type;
//点击按钮跳转页面
document.getElementById('v-step-1').click()
}
//如果已跳转至第二步页面,则成功展示第二步
else if (this.$route.path === '/second-step-page') {
//记录Cookies,按需取舍
this.setHadTourCookies()
resolve('foo')
}
})
}
],
myOptions: {
useKeyboardNavigation: false, //是否使用键盘控制引导
labels: { //配置按钮显示名称
buttonSkip: '跳过引导',
buttonPrevious: '上一步',
buttonNext: '下一步',
buttonStop: '完成引导'
},
highlight: true,//步骤Dom是否需要高亮,默认高亮是一个小shadow,若需要大遮罩请看style设置
},
myCallbacks: {
//跳过引导的时候也记录Cookies
onSkip: this.setHadTourCookies,
},
pendingStatus:'', // 添加一个标志来记录页面跳转状态
}
},
mounted() {
//按需判断何时开始引导
if (!Cookies.get('hadTour')) {
//一定要在第一步骤渲染完,才开始引导,可以放在第一步骤所在组件的mounted
this.$tours['myTour'].start()
}
},
methods: {
setHadTourCookies() {
//此处设置Cookies,按个人需求取舍
Cookies.set('hadTour', true, {
expires: new Date(new Date().getTime() + 24 * 60 * 60 * 1000),
})
},
//新页面时,domDone获取页面加载成功的信息,并手动调用下一步的方法
domDone() {
//按pendingStatus控制上一步下一步
if (this.pendingStatus === 'next') {
this.$tours['myTour1'].nextStep()
this.pendingStatus = '';
} else if (this.pendingStatus === 'previous') {
this.$tours['myTour1'].previousStep()
this.pendingStatus = '';
}
}
},
</script>
<style lang="scss" scoped>
//官方推荐的写法,将shadow设置很大,即变成了遮罩(感觉还挺机智的)
.v-tour__target--highlighted {
box-shadow: 0 0 0 99999px rgba(0, 0, 0, .4) !important;
}
</style>
//子组件
<template>
<div>
<div class="item" id="v-step-2">步骤二</div>
</div>
</template>
<script>
export default {
mounted() {
//页面对应的dom加载结束时,通知父组件
//不一定在mounted,也可以是数据接口调用完成后,按个人需求放置
if (this.$tours['myTour']) {
this.$emit('domDone')
}
},
</script>