vue左右侧联动滚动的实现代码


Posted in Javascript onJune 06, 2018

本文介绍了vue左右侧联动滚动的实现代码,分享给大家,具体如下:

实现功能:

  1. 点击左侧,右侧滚动到相应位置,
  2. 滚动右侧, 左侧滚动到相应位置

vue左右侧联动滚动的实现代码

布局结构:

vue左右侧联动滚动的实现代码

开源滚动库:

better-scroll.js

技术要点:

1.<scroll>是对紧邻的元素生效

如:

<scroll class='foods-wrapper'>
  <ul class=content>
   <li></li>
  </ul>
 </scroll>

初始化在<ul>元素上

2.foods-wrapper的高度小于content高度时才会发生滚动

3.点击左侧菜单列表时,只需要计算右侧对应的偏移距离 或是 计算对应的移动到的元素即可

方法一: 计算移动距离, 用scrollTo()方法

for (let i = 0; i < index; i++) {
  height += this.$refs.item[i].offsetHeight
 }
 this.$refs.foodsWrapper.scrollTo(0, -height)

方法二: 计算移动到的元素,用scrollToElement()方法

let foodsEle = this.$refs.foodsUl.getElementsByClassName('item')[index]
 this.$refs.foodsWrapper.scrollToElement(foodsEle, 400)

4.滚动右侧列表时,会稍复杂一些.

4.1. 因为需要知道滚动的元素在哪个item列表区间, 因此需要计算右侧五组item距离顶部的距离

_heightArr () {
 let h = 0
 let list = this.$refs.item
 list.forEach((item, i) => {
  h += list[i].clientHeight
  this.itemHeight.push(h)
 })
  console.log(this.itemHeight) //[0, 481, 850, 2227, 2820, 3189]
}

4.2 时时监听滚动距离

需要在<scroll>中加以下参数

<scroll class='foods-wrapper' :listenScroll=listenScroll :probeType = 'probeType' @scroll=scroll>

其中 listenScroll probeType参数 在created中定义:

created () {
  this.listenScroll = true
  this.probeType = 3
 }

而@scroll=scroll是在scroll.vue中代理过来的方法:

//scroll.vue
 if (this.listenScroll) {
  let me = this
  this.scroll.on('scroll', (position) => {
   me.$emit('scroll', position) //参数position: position:{x:-10, y:24}
  })
 }

posiiton.y就是需要实时监听的参数,即:

scroll (position) {
 this.scrolly = position.y
}

其中 scrolly 需要在data中提前定义:

data () {
  return {
   scrolly: -1
  }
 }

然后在watch中监听scrolly变化即可:

watch: {
  scrolly (newy) {
   if (newy >= 0) this.currentIndex = 0
   let itemHeight = this.itemHeight
   for (let i = 0; i < itemHeight.length - 1; i++) {
    let h1 = itemHeight[i]
    let h2 = itemHeight[i + 1]
    if (-newy >= h1 && -newy < h2) {
     this.currentIndex = i
     return
    }
   }
  }
 }

代码部分:

//左侧结构
 <scroll class='menu-wrapper'>
  <ul>
   <li 
    v-for='(item,index) in foodsList' 
    :key=index 
     class=item 
    :class="{active:currentIndex === index}" 
    @click=selectMenu(index)
   >
    <span>{{item.name}}</span>
   </li>
  </ul>
 </scroll>


//右侧结构
 <scroll class='foods-wrapper' ref=foodsWrapper :listenScroll=listenScroll :probeType = 'probeType' @scroll=scroll>
  <ul ref=foodsUl> 
   <li v-for='(item,index) in foodsList' :key=index class=item ref=item :data-index=index>
    <div class=title><span class='title-name'>{{item.name}}</span><span>{{item.description}}</span></div>
    <ul>
     <li v-for='(food,i) in item.foods' :key=i class=food>
     //.........
     //略去右侧详情代码
     </li>
    </ul>
   </li>
  </ul>
 </scroll>

//js部分
<script>
import Scroll from "base/scroll"
const H = 112
export default {
 data () {
  return {
   currentIndex: 0,
   offset: 0,
   scrolly: -1
  }
 },
 created () {
  this.listenScroll = true
  this.probeType = 3
  this.itemHeight = [0]
 },
 mounted () {
  this.$nextTick(() => {
   this._heightArr()
  }, 20);
 },
 methods: {
  selectMenu (index) {
   let height = 0
   this.currentIndex = index

   for (let i = 0; i < index; i++) {
    height += this.$refs.item[i].offsetHeight
   }

   let foodsEle = this.$refs.foodsUl.getElementsByClassName('item')[index]
   this.$refs.foodsWrapper.scrollToElement(foodsEle, 400)
   // this.$refs.foodsWrapper.scrollTo(0, -height)
   this.offset = height
  },
  scroll (position) {
   this.scrolly = position.y
  },
  _heightArr () {
   let h = 0
   let list = this.$refs.item
   list.forEach((item, i) => {
    h += list[i].clientHeight
    this.itemHeight.push(h)
   })
  }
 },
 watch: {
  scrolly (newy) {
   if (newy >= 0) this.currentIndex = 0
   let itemHeight = this.itemHeight
   for (let i = 0; i < itemHeight.length - 1; i++) {
    let h1 = itemHeight[i]
    let h2 = itemHeight[i + 1]
    if (-newy >= h1 && -newy < h2) {
     this.currentIndex = i
     return
    }
   }
  }

 },
 components: {
  Scroll
 }


}
</script>
//scroll.vue
<template>
 <div ref=wrapper>
  <slot></slot> 
 </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
 props: {
  probeType: {
   type: Number,
   default: 1//* 1 滚动的时候会派发scroll事件,会截流。 * 2 滚动的时候实时派发scroll事件,不会截流。 * 3 除了实时派发scroll事件,在swipe的情况下仍然能实时派发scroll事件
  },
  click: {
   type: Boolean,
   default: true
  },
  scrollX: {
   type: Boolean,
   default: false
  },
  data: {
   type: Array,
   default: null
  },
  listenScroll: {
   type: Boolean,
   default: false
  },

 },
 mounted () {
  this.$nextTick(() => {
   this.initScroll()
  }, 20)
 },
 methods: {
  initScroll () {
   if (!this.$refs.wrapper) return
   this.scroll = new BScroll(this.$refs.wrapper, {
    probeType: this.probeType,
    click: this.click,
    scrollX: this.scrollX
   })

   if (this.listenScroll) {
    let me = this
    this.scroll.on('scroll', (position) => {
     me.$emit('scroll', position)

    })
   }
  },
  enable () {
   this.scroll && this.scroll.enable()
  },
  disable () {
   this.scroll && this.scroll.disable()
  },
  refresh () {
   this.scroll && this.scroll.refresh()
  },
  scrollTo () {
   this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
  },

  scrollToElement () {
   this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
  }

 },
 watch: {
  data () {
   setTimeout(() => {
    this.scroll.refresh()
   }, 20)
  }
 }

}
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 命名空间以提高代码重用性
Nov 13 Javascript
让浏览器非阻塞加载javascript的几种方法小结
Apr 25 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
Feb 26 Javascript
原生Js页面滚动延迟加载图片实现原理及过程
Jun 24 Javascript
ExtJS判断IE浏览器类型的方法
Feb 10 Javascript
Javascript变量的作用域和作用域链详解
Apr 02 Javascript
JavaScript运行过程中的“预编译阶段”和“执行阶段”
Dec 16 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
Sep 02 Javascript
jquery实现动态改变css样式的方法分析
May 27 jQuery
js回文数的4种判断方法示例
Jun 04 Javascript
Vue 动态添加路由及生成菜单的方法示例
Jun 20 Javascript
JavaScript对象字面量和构造函数原理与用法详解
Apr 18 Javascript
Express本地测试HTTPS的示例代码
Jun 06 #Javascript
微信小程序仿美团城市选择
Jun 06 #Javascript
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
Jun 05 #jQuery
详解封装基础的angular4的request请求方法
Jun 05 #Javascript
React.js绑定this的5种方法(小结)
Jun 05 #Javascript
微信小程序实现城市列表选择
Jun 05 #Javascript
vue.js将时间戳转化为日期格式的实现代码
Jun 05 #Javascript
You might like
php对称加密算法示例
2014/05/07 PHP
php中curl、fsocket、file_get_content三个函数的使用比较
2014/05/09 PHP
Zend Framework教程之Zend_Registry对象用法分析
2016/03/22 PHP
php常用正则函数实例小结
2016/12/29 PHP
简单的JS多重继承示例
2008/03/13 Javascript
extjs 学习笔记(一) 一些基础知识
2009/10/13 Javascript
javascript是怎么继承的介绍
2012/01/05 Javascript
javascript实现的一个带下拉框功能的文本框
2014/05/08 Javascript
jqueryUI里拖拽排序示例分析
2015/02/26 Javascript
iPhone手机上搭建nodejs服务器步骤方法
2015/07/06 NodeJs
jQuery实现的导航下拉菜单效果示例
2016/09/05 Javascript
jquery 给动态生成的标签绑定事件的几种方法总结
2018/02/24 jQuery
基于vue-cli3和element实现登陆页面
2019/11/13 Javascript
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
[01:05]主宰至宝剑心之遗
2017/03/16 DOTA
[01:05:41]EG vs Optic Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
[02:49:21]2019完美盛典全程录像
2019/12/08 DOTA
初探利用Python进行图文识别(OCR)
2019/02/26 Python
Python中Numpy mat的使用详解
2019/05/24 Python
使用python telnetlib批量备份交换机配置的方法
2019/07/25 Python
利用Pytorch实现简单的线性回归算法
2020/01/15 Python
python pprint模块中print()和pprint()两者的区别
2020/02/10 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
2020/04/24 Python
python3 kubernetes api的使用示例
2021/01/12 Python
STAY JAPAN台湾:预订日本民宿
2018/07/22 全球购物
Python面试题集
2012/03/08 面试题
企业员工培训感言
2014/02/26 职场文书
搞笑婚礼主持词
2014/03/13 职场文书
文化宣传方案
2014/03/13 职场文书
出租房屋协议书
2014/09/14 职场文书
2014年教研组工作总结
2014/11/26 职场文书
首都博物馆观后感
2015/06/05 职场文书
2015七夕情人节宣传语
2015/07/14 职场文书
2015中秋节晚会开场白
2015/07/30 职场文书
为什么MySQL 删除表数据 磁盘空间还一直被占用
2021/10/16 MySQL
CSS中使用grid布局实现一套模板多种布局
2022/07/15 HTML / CSS