首页 > 编程 > JavaScript > 正文

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

2019-11-19 13:42:51
字体:
来源:转载
供稿:网友

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

实现功能:

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

布局结构:

开源滚动库:

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 = 112export 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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表