项目中经常遇到区域超出部分会出现滚动条,滚动条在pc端可以通过鼠标滚轮控制上下,在移动端可以通过鼠标拖动页面进行滚动,这两种场景都是符合用户习惯,然而这种滚动条一般都是竖【vertical】项滚动条,如果pc端出现横向滚动条【horizontal】,在不做处理的情况下,你只能用鼠标拖动横向滚动条按钮【scrollerbar】展示滚动区域,而且为了美观,一般滚动条会进行样式编写或者隐藏,那么横向区域默认情况下就没法滚动。
二、描述
现为了解决pc端滚动区域能像移动端一样,能够通过鼠标拖动滚动区域直接进行滚动,如图所示
pc端滚动示例图
滚动实例用到知识点如下:
- 采用vue-cli3+iscroll.js组合的方式;
- 使用 vue 自定义指令实现 iscroll 实例化和参数配置;
- 实现横向滚动区域和竖向滚动区域之间的联动;
- 实现横向滚动条居中显示和使用scrollIntoView()方法的差别
三、自定义指令 v-iscroll
1、新建指令文件
这里使用 vue 自定义指令初始化 iscroll 实例,在 vue-cli3 项目目录下新建vIscroll.js,文件代码如下:
const IScroll = require('iscroll') const VIScroll = { install: function (Vue, options) { Vue.directive('iscroll', { inserted: function (el, binding, vnode) { let callBack let iscrollOptions = options <!--vue组件中绑定的两个参数 option、instance--> const option = binding.value && binding.value.option const func = binding.value && binding.value.instance // 判断输入参数 const optionType = option "htmlcode">import Vue from 'vue' import App from './App.vue' import "./assets/reset.css" // 加载scroll指令 import VIscroll from './directive/vIscroll' Vue.use(VIscroll) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')使用指令,摘自 tabList.vue 组件部分代码如下:
<template> <div class="tab-container"> <div class="scroll-container" v-iscroll="{ option: iscrollConf, instance: getIscroll }" ref="scrollContainer" > <ul class="tab-li-container" ref="tabLiContainer" > <li class="tab-li-item" v-for="(item, index) in list" :key="item.id" :id="item.id" ref="tabItem" @click="tabEvent(item, index)" > <div class="item" :class="{ 'item-active': currentId == item.id }" >{{item.num}}</div> </li> </ul> </div> <div class="tab-left" @click="tabBtnEvent('left')" ><</div> <div class="tab-right" @click="tabBtnEvent('right')" </div> </div> </template> <script> export default { props: ['list'], data () { return { iscrollConf: { bounce: true, mouseWheel: true, click: true, scrollX: true, scrollY: false }, currentId: null, currentIndex: 0, myScroll: null } }, mounted () { this.$refs.tabLiContainer.style.width = this.$refs.tabItem[0].offsetWidth * this.list.length + 'px' this.$nextTick(() => { this.myScroll.refresh() }) }, methods: { tabEvent (item, currentIndex) { <!--点击某个li 按钮事件处理逻辑--> }, tabBtnEvent (direction) { <!--左右切换逻辑事件--> }, getIscroll (iscroll) { this.myScroll = iscroll } }, watch: { list: { handler (l) { this.currentId = l[0].id }, immediate: true, deep: true } } } </script> <style scoped> // 样式 </style>上述代码中 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() 方法进行详细注释:
<template> <div id="app"> <TabList :list="list" @switchTab="switchTab" ></TabList> <!-- v-iscroll="defalutOption" --> <div v-iscroll="{ option: defalutOption, instance: getIscroll }" class="tab-content-container" ref="detailItemContainer" > <ul class="tab-list-container"> <li v-for="item in list" :key="item.id" class="list-item" ref="detailItem" > <div>{{item.value}}</div> </li> </ul> </div> </div> </template> <script> import TabList from './components/tabList.vue' export default { name: 'App', components: { TabList, }, data () { return { list: [ { id: 1, value: '这是第1题', num: 1 }, <!--...省略数据展示--> { id: 16, value: '这是第16题', num: 16 } ], defalutOption: { bounce: true, mouseWheel: true, click: true, scrollX: false, scrollY: true }, myScroll: null } }, methods: { switchTab (currentId, currentIndex) { <!--对选中的当前项,这里就是“3”按钮对应的“这是第3题”,求出它距离父元素的上边距offsetTop值--> const offsetTop = this.$refs.detailItem[currentIndex].offsetTop <!--滚动的范围不能超过这个滚动体的底部,这里面用到iscroll的属性maxScrollY--> const y = offsetTop >= Math.abs(this.myScroll.maxScrollY) "htmlcode">this.$refs.tabItem[this.currentIndex].scrollIntoView({ behavior: "smooth", inline: "center", block: 'nearest' })这里在横向滚动区域添加了一对左右按钮,实现切换功能,如图所示:
切换按钮示例图
切换按钮事件方法就是通过改变上一个、下一个按钮下标,调用方法,实现切换功能,切换事件方法逻辑如下:
tabBtnEvent (direction) { const max = this.$refs.tabItem.length if (direction === 'left' && this.currentIndex > 0) { this.currentIndex-- } if (direction === 'right' && this.currentIndex < max - 1) { this.currentIndex++ } <!--调用单击按钮事件--> this.tabEvent(this.$refs.tabItem[this.currentIndex], this.currentIndex) },下面对 单击按钮事件 添加居中逻辑,详细代码和解析图如下,可以对比查看:
居中计算图
tabEvent (item, currentIndex) { this.currentId = item.id this.currentIndex = currentIndex // 获取滚动容器的长度的一半,即中间点 const scrollContainerHalfWidth = this.$refs.scrollContainer.offsetWidth / 2 // 获取单个item的一半长度 const tabItemHalfWidth = this.$refs.tabItem[currentIndex].offsetWidth / 2 // 求取插值,就是开始到中间开始位置的距离 const halfDistance = scrollContainerHalfWidth - tabItemHalfWidth // 求取当前item的相对总长度的偏移量 const currentItemOffsetLeft = this.$refs.tabItem[currentIndex].offsetLeft // scroll 移动到中间的值 const x = 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端滚动问题,希望对大家有所帮助!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com