vue中利用iscroll.js解决pc端滚动问题
项目中经常遇到区域超出部分会出现滚动条,滚动条在pc端可以通过鼠标滚轮控制上下,在移动端可以通过鼠标拖动页面进行滚动,这两种场景都是符合用户习惯,然而这种滚动条一般都是竖【vertical】项滚动条,如果pc端出现横向滚动条【horizontal】,在不做处理的情况下,你只能用鼠标拖动横向滚动条按钮【scrollerbar】展示滚动区域,而且为了美观,一般滚动条会进行样式编写或者隐藏,那么横向区域默认情况下就没法滚动。
二、描述
现为了解决pc端滚动区域能像移动端一样,能够通过鼠标拖动滚动区域直接进行滚动,如图所示
pc端滚动示例图
滚动实例用到知识点如下:
- 采用vue-cli3+iscroll.js组合的方式;
- 使用vue自定义指令实现iscroll实例化和参数配置;
- 实现横向滚动区域和竖向滚动区域之间的联动;
- 实现横向滚动条居中显示和使用scrollIntoView()方法的差别
三、自定义指令v-iscroll
1、新建指令文件
这里使用vue自定义指令初始化iscroll实例,在vue-cli3项目目录下新建vIscroll.js,文件代码如下:
constIScroll=require('iscroll')
constVIScroll={
install:function(Vue,options){
Vue.directive('iscroll',{
inserted:function(el,binding,vnode){
letcallBack
letiscrollOptions=options
constoption=binding.value&&binding.value.option
constfunc=binding.value&&binding.value.instance
//判断输入参数
constoptionType=option?[].toString.call(option):undefined
constfuncType=func?[].toString.call(func):undefined
//兼容google浏览器拖动
el.addEventListener('touchmove',function(e){
e.preventDefault()
})
//将参数配置到newIScroll(el,iscrollOptions)中
if(optionType==='[objectObject]'){
iscrollOptions=option
}
if(funcType==='[objectFunction]'){
callBack=func
}
//使用vnode绑定iscroll是为了让iscroll对象能够夸状态传递,避免iscroll重复建立
//这里面跟官方网站constmyScroll=newIScroll('#wrapper',option)初始化一样
vnode.scroll=newIScroll(el,iscrollOptions)
//如果指令传递函数进来,把iscroll实例传递出去
if(callBack)callBack(vnode.scroll)
},
componentUpdated:function(el,binding,vnode,oldVnode){
//将scroll绑定到新的vnode上,避免多次绑定
vnode.scroll=oldVnode.scroll
//使用settimeout让refresh跳到事件流结尾,保证refresh时数据已经更新完毕
setTimeout(()=>{
vnode.scroll.refresh()
},0)
},
unbind:function(el,binding,vnode,oldVnode){
//解除绑定时要把iscroll销毁
vnode.scroll=oldVnode.scroll
vnode.scroll.destroy()
vnode.scroll=null
}
})
}
}
module.exports=VIScroll
这里附上iscroll.js5官方文档地址,iscrollnpm包地址,相关属性和方法自行查看。
2、加载引用指令
首先在main.js中加载指令:
importVuefrom'vue'
importAppfrom'./App.vue'
import"./assets/reset.css"
//加载scroll指令
importVIscrollfrom'./directive/vIscroll'
Vue.use(VIscroll)
Vue.config.productionTip=false
newVue({
render:h=>h(App),
}).$mount('#app')
使用指令,摘自tabList.vue组件部分代码如下:
{{item.num}}<>
上述代码中v-iscroll指令传入两个字段参数:
option:配置iscroll参数,这里面注意scrollX,scrollY两个属性,代表的是横向还是竖向滚动;
instance:回调方法的调用,vIscroll.js中执行回调方法,通过该组件方法getIscroll()获取到iscroll的实例。
3、上下滚动区域联动
上面的代码可以解决开篇场景中的问题,现在实现上下区域联动,通过点击横向滚动条某个按钮,使其变成选中状态,然后竖向滚动条对应的项跳到首位,如图所以:
联动示例图
3-1、联动实现方法
点击按钮的方法:
tabEvent(item,currentIndex){
this.currentId=item.id
this.currentIndex=currentIndex
...
this.$emit("switchTab",this.currentId,this.currentIndex)
},
竖向滚动区域组件【App.vue】代码部分如下,并对switchTab()方法进行详细注释:
{{item.value}}
这里面用到的都是iscroll插件自带的属性和方法进行滚动边界的判断和滚动,比用JavaScript方法方便的多,而且用了iscroll作为滚动容器,已经在vIscroll.js禁用了相关浏览器默认事件。
3-2、居中显示
这里JavaScript有个scrollIntoView()方法,官方文档链接,这个方法让当前的元素滚动到浏览器窗口的可视区域内。关键缺点是,如果横向滚动和竖向滚动都同时用到这个方法,只能保证一个滚动区域有效,另一个会不滚动。
使用scrollIntoView()方法配置如下:
this.$refs.tabItem[this.currentIndex].scrollIntoView({
behavior:"smooth",
inline:"center",
block:'nearest'
})
这里在横向滚动区域添加了一对左右按钮,实现切换功能,如图所示:
切换按钮示例图
切换按钮事件方法就是通过改变上一个、下一个按钮下标,调用方法,实现切换功能,切换事件方法逻辑如下:
tabBtnEvent(direction){
constmax=this.$refs.tabItem.length
if(direction==='left'&&this.currentIndex>0){
this.currentIndex--
}
if(direction==='right'&&this.currentIndex
this.tabEvent(this.$refs.tabItem[this.currentIndex],this.currentIndex)
},
下面对单击按钮事件添加居中逻辑,详细代码和解析图如下,可以对比查看:
居中计算图
tabEvent(item,currentIndex){
this.currentId=item.id
this.currentIndex=currentIndex
//获取滚动容器的长度的一半,即中间点
constscrollContainerHalfWidth=this.$refs.scrollContainer.offsetWidth/2
//获取单个item的一半长度
consttabItemHalfWidth=this.$refs.tabItem[currentIndex].offsetWidth/2
//求取插值,就是开始到中间开始位置的距离
consthalfDistance=scrollContainerHalfWidth-tabItemHalfWidth
//求取当前item的相对总长度的偏移量
constcurrentItemOffsetLeft=this.$refs.tabItem[currentIndex].offsetLeft
//scroll移动到中间的值
constx=halfDistance-currentItemOffsetLeft
this.myScroll.scrollTo(x,0)
this.$emit("switchTab",this.currentId,this.currentIndex)
},
4、总结
1、整个实例用的都是iscroll插件相关属性实现的滚动,避免同时使用JavaScript方法造成的代码混乱;
2、利用自定义指令的方式有效的避免了传统实例化iscroll带来的代码冗余,使其方便简洁;
3、本实例滚动选项都是字符串,如果出现图片的情况,合理使用iscroll.refresh()方法,在正确的时期重新计算滚动区域,避免滚动边界受限;
总结
以上所述是小编给大家介绍的vue中利用iscroll.js解决pc端滚动问题,希望对大家有所帮助!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。