# uniapp用户引导组件fast-guide

#### 介绍
简介：一个使用便捷的用户引导组件，支持自动/手动聚焦，组件聚焦，支持根据步骤聚焦引导，支持自定义聚焦提示词。
框架兼容性：支持vue2、vue3
平台兼容性：支持h5、小程序、app

***  
### 功能&特点
* 【配置简单灵活】仅需维护一个数组，绑定操作方法即可使用功能。
* 【强大的兼容性】支持vue2，vue3，支持h5、app及各家小程序。
* 【流畅的交互体验】聚焦切换全部采用动画过渡，丝滑流畅！

*** 

#### 开发文档


```vue
/**
 * guide 引导弹窗
 * @description 引导组件，用于教学提示、用户操作引导等内容，支持自定义组件节点自动聚焦和手动设置相对位置聚焦。组件只提供容器，内部内容由用户自定义
 * @tutorial //git地址
 * @property {Boolean}			show				是否展示弹窗 (默认 false )
 * @property {Number}			index				当前步骤索引(默认 0 )
 * @property {String | Number}	duration			动画时长
 * @property {String}			unit				换算单位
 * @property {Array}			list				步骤列表
 * @property {Object}			{
 * 								@property{String}	ref					要聚焦的子组件的ref
 * 								@property{String}	target				当前组件/子组件中的选择器标识
 * 								@property{String}	position			提示框展示位置'top'/'bottom'
 * 								@property{String}	msg					提示框文字
 * 								@property{String}	msgStyles			提示框自定义样式
 * 								@property{String}	width				自定义聚焦范围的宽度
 * 								@property{String}	height				自定义聚焦范围的高度
 * 								@property{String}	left				自定义聚焦范围的左侧偏移量 left/right仅生效一个	使用自定义聚焦后ref、target属性将失效
 * 								@property{String}	right				自定义聚焦范围的右侧偏移量 left/right仅生效一个	使用自定义聚焦后ref、target属性将失效
 * 								@property{String}	top					自定义聚焦范围的上侧偏移量 top/bottom仅生效一个	使用自定义聚焦后ref、target属性将失效
 * 								@property{String}	bottom				自定义聚焦范围的下侧偏移量 top/bottom仅生效一个	使用自定义聚焦后ref、target属性将失效
								}					list步骤列表内部参数说明
 * @event {Function} open   	弹出层打开
 * @event {Function} close  	弹出层收起
 * @event {Function} focus  	聚焦区域点击事件
 * @event {Function} mask		遮罩区域点击事件
 * @event {Function} next   	执行下一步
 * @event {Function} last   	执行上一步
 * @event {Function} skip   	跳过所有步骤
 * @event {Function} finish 	结束引导
 * @event {Function} getQuery	获取兄弟组件布局查询对象
 * @example <popup-guide :show="guideShow" :list="guideList" :index="guideIndex" @next="guideNext" @last="guideLast" @skip="guideSkip" @finish="guideFinish" ></popup-guide>
 */
```



#### 示例代码

```vue
<template>
	<view class="content" id="content">
		<image class="logo" src="/static/logo.png"></image>
		<view class="" style="padding-left: 20rpx;">
			<view class="text-area">
				<text class="title">{{title}}123</text>
			</view>
		</view>
		
		<view @click="again" class="again">
			再来一次
		</view>
		<Test ref="TestNode"></Test>
		<view class="" style="margin: 100rpx 0 0 150rpx;background-color: antiquewhite;padding: 50rpx;">
			自定义聚焦
		</view>
		
		<!-- 普通用法 -->
		<fast-guide
			:show="guideShow" 
			:list="guideList" 
			:index="guideIndex"
			@open="guideOpen"
			@close="guideClose"
			@focus="guideFocus"
			@mask="guideMask"
			@next="guideNext" 
			@last="guideLast" 
			@skip="guideSkip" 
			@finish="guideFinish"
			@getQuery="getQuery"
		></fast-guide>
		
		<!-- 作用域插槽用法 -->
		<!-- <fast-guide 
			:show="guideShow" 
			:list="guideList" 
			:index="guideIndex"
			@open="guideOpen"
			@close="guideClose"
			@focus="guideFocus"
			@mask="guideMask"
			@next="guideNext" 
			@last="guideLast" 
			@skip="guideSkip" 
			@finish="guideFinish"
			@getQuery="getQuery"
		>
			<template #message="{msg}" >
				<view class="" style="color: #333;">
					【作用域插槽】{{msg}}
				</view>
			</template>
		</fast-guide> -->
	</view>
</template>

<script>
	import Test from './component/test.vue'
	
	export default {
		components:{
			Test
		},
		data() {
			return {
				title: 'Hello',
				
				guideShow:false,
				guideList:[
					
					{
						target:'#content',
						position:'bottom',
						msg:'这是第一步'
					},
					{
						target:'.logo',
						msg:'这是第二步【自定义样式】',
						position:'bottom',
						msgStyles:{
							'width':'60vw',
							'color':'#ff5500'
						}
					},
					{
						target:'.text-area',
						position:'top',
						msg:'这是第三步'
					},
					{
						// 使用ref指定组件聚焦时必须定义getQuery回调
						ref:'TestNode',
						target:'.children-node',
						position:'bottom',
						msg:'这是【子组件】聚焦，使用ref指定组件聚焦时必须定义getQuery回调'
					},
					{
						// 使用ref指定组件聚焦时必须定义getQuery回调
						ref:'TestNode',
						target:'.deep-children-node',
						position:'bottom',
						msg:'这是【嵌套子组件】聚焦，使用ref指定组件聚焦时必须定义getQuery回调'
					},
					{
						width:300,
						height:180,
						
						right:150,
						top:900,
						position:'top',
						msg:'这是自定义聚焦范围，支持响应式单位'
					},
					
					{
						target:'.again',
						position:'bottom',
						msg:'点击此处可以重新体验'
					},
					
				],
				guideIndex:0,
				
				testDom:{}
			}
		},
		onLoad() {

		},
		mounted() {
			this.guideShow = true
		},
		methods: {
			guideOpen(e){
				console.log(e,'guideOpen')
				uni.showToast({
					title:'打开引导',
					icon:'none'
				})
			},
			guideClose(e){
				console.log(e,'guideClose')
				uni.showToast({
					title:'关闭引导',
					icon:'none'
				})
			},
			guideFocus(e){
				console.log(e,'guideFocus')
				uni.showToast({
					title:'聚焦范围点击事件',
					icon:'none'
				})
			},
			guideMask(e){
				console.log(e,'guideMask')
				uni.showToast({
					title:'遮罩范围点击事件',
					icon:'none'
				})
			},
			getQuery(fn){
				//当使用ref属性进行引导时，此处传入需要聚焦的组件的父组件实例对象
				console.log('父组件事件被触发，子组件获取兄弟组件布局查询对象')

				// #ifdef VUE2
				// vue2传入this
				fn.call(this)
				// #endif
				
				// #ifdef VUE3
				// import { getCurrentInstance } from 'vue'
				// vue3通过getCurrentInstance获取this
				fn.call(getCurrentInstance().proxy)
				// #endif
			},
			guideNext(e){
				console.log(e,'guideNext')
				this.guideIndex++
			},
			guideLast(e){
				console.log(e,'guideLast')
				this.guideIndex--
			},
			guideSkip(e){
				console.log(e,'guideSkip')
				this.guideShow = false
			},
			guideFinish(e){
				console.log(e,'guideFinish')
				this.guideShow = false
			},
			again(){
				this.guideIndex = 0
				this.guideShow = true
			}
		}
	}
</script>

<style>
	.content {
		width: 100vw;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
	
	/* 深度选择修改步骤盒子样式 */
	/* /deep/ .step-btn{
		color: red;
	} */
</style>

```

