Vue实现左右菜单联动实现

2018-08-11 admin

title: Vue实现左右菜单联动实现 date: 2018-08-11 16:31:34 tags:

top: 100

知乎

个人博客

Github

源码传送门:Rain120/vue-study

之前在外卖软件上看到这个左右联动的效果,觉得很有意思,所以就尝试使用Vue来实现,将这个联动抽离成为一个单独的组件,废话少说,先来一张效果图。

Vue实现左右菜单联动效果图

这个组件分为两个部分,1、左菜单;2、右菜单。 左菜单的DOM结构

<scroll
  class="left-menu"
  :data="leftMenu"
  ref="leftMenu">
  <div class="left-menu-container">
    <ul>
      <li
        class="left-item"
        ref="leftItem"
        :class="{'current': currentIndex === index}"
        @click="selectLeft(index, $event)"
        v-for="(item, index) in leftMenu"
        :key="index">
        <p class="text">{{item}}</p>
      </li>
    </ul>
  </div>
</scroll>

右菜单的DOM结构

<scroll
  class="right-menu"
  :data="rightMenu" 
  ref="rightMenu"
  @scroll="scrollHeight"
  :listenScroll="true"
  :probeType="3">
  <div class="right-menu-container">
    <ul>
      <li class="right-item" ref="rightItem" v-for="(items, i) in rightMenu" :key="i">
        <div class="data-wrapper">
          <div class="title">{{items.title}}</div>
          <div class="data" v-for="(item, j) in items.data" :key="j">{{item}}</div>
        </div>
      </li>
    </ul>
  </div>
</scroll>

这里是为了做demo,所以在数据上只是单纯捏造。

当然因为这是个子组件,我们将通过父组件传递props,所以定义props

props: {
  leftMenu: {
    required: true,
    type: Array,
    default () {
      return []
    }
  },
  rightMenu: {
    required: true,
    type: Array,
    default () {
      return []
    }
  },
}

原理图

在这个业务场景中,我们的实现方式是根据右边菜单滚动的高度来计算左边菜单的位置,当然左边菜单也可以通过点击来确定右边菜单需要滚动多高的距离,那么我们如何获得该容器滚动的距离呢? 之前一直在使用better-scroll,通过阅读文档,我们知道它有有scroll事件,我们可以通过监听这个事件来获取滚动的pos scroll事件

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

所以我们在右边菜单的scroll组件上监听scroll事件

@scroll="scrollHeight"

method

scrollHeight (pos) {
  console.log(pos);
  this.scrollY = Math.abs(Math.round(pos.y))
},

我们将监听得到的pos打出来看看 监听scroll事件,得到pos

我们可以看到控制台打出了当前滚动的pos信息,因为在移动端开发时,坐标轴和我们数学中的坐标轴相反,所以上滑时y轴的值是负数

移动开发坐标轴

所以我们要得到每一块li的高度,我们可以通过拿到他们的DOM

 _calculateHeight() {
  let lis = this.$refs.rightItem;
  let height = 0
  this.rightHeight.push(height)
  Array.prototype.slice.call(lis).forEach(li => {
    height += li.clientHeight
    this.rightHeight.push(height)
  })
console.log(this.rightHeight)
}

我们在created这个hook之后调用这个计算高度的函数

 _calculateHeight() {
  let lis = this.$refs.rightItem;
  let height = 0
  this.rightHeight.push(height)
  Array.prototype.slice.call(lis).forEach(li => {
    height += li.clientHeight
    this.rightHeight.push(height)
  })
  console.log(this.rightHeight)
}

得到右边菜单高度

当用户在滚动时,我们需要计算当前滚动距离实在那个区间内,并拿到他的index

找到滚动位置对应的index 找到滚动位置对应的index

computed: {
  currentIndex () {
    const { scrollY, rightHeight } = this
    const index = rightHeight.findIndex((height, index) => {
      return scrollY >= rightHeight[index] && scrollY < rightHeight[index + 1]
    })
    return index > 0 ? index : 0
  }
}

所以当前应该是左边菜单index = 1的菜单项active 以上是左边菜单根据右边菜单的滑动联动的实现,用户也可以通过点击左边菜单来实现右边菜单的联动,此时,我们给菜单项加上click事件

@click="selectLeft(index, $event)"

这里加上$event是为了区分原生点击事件还是better-scroll派发的事件

selectLeft (index, event) {
  if (!event._constructed) {
    return
  }
  let rightItem = this.$refs.rightItem
  let el = rightItem[index]
  this.$refs.rightMenu.scrollToElement(el, 300)
},

到这里我们就基本上完成了这些需求了

原文链接:https://segmentfault.com/a/1190000015970841

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-37769.html

文章标题:Vue实现左右菜单联动实现

相关文章
javaScript+turn.js实现图书翻页效果实例代码
为了实现图书翻页的效果我们在网上可以看到很多教程 在这里推荐turn.js 网上的turn.js 有api 不过是英文的  很多人看起来不方便 .关于代码也是奇形怪状在这里我将详细讲解如何使用turn.js实现翻页效果 ,本篇文章只是讲解 ...
2017-03-16
vue.js实现请求数据的方法示例
vue2.0示例代码如下: var vm = new Vue({ el:&quot;#list&quot;, data:{ gridData: &quot;&quot;, }, ...
2017-03-20
最细致的vue.js基础语法 值得收藏!
介绍 前段时间接触到一个库叫做Vue.js, 个人感觉很棒,所以整理了一篇博文做个介绍。 Vue读音/vju:/,和view类似。是一个数据驱动的web界面库。Vue.js只聚焦于视图层,可以很容易的和其他库整合。代码压缩后只有24kb。 ...
2017-03-21
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
直接贴代码了: 先上输入前的样子: &lt;style&gt; #example{margin:100px auto;width:600px;} .show{margin:10px;} #searchText{display: block...
2017-03-17
js实现鼠标左右移动,图片也跟着移动效果
效果:鼠标往左移,图片对应右移,鼠标往右移,图片就左移动。图片距离越远偏移距离越大。 思路:首先获取图片原先的距离。设置一个变化值,图片的最终距离等于原先的距离加上变化值 布局:大盒子里面是图片,大盒子position:relative;图...
2017-02-17
js实现文字向上轮播功能
话不多说,请看实现代码: &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; &lt;meta charset=&quot;UTF-8&quot;&gt;...
2017-03-10
纯css实现窗户玻璃雨滴逼真效果
这里仅是用CSS技术来演示这样的一个场景,可能并不太实用。然而这是一个探索CSS新功能的最佳机会。可以让你尝试使用一些新特性和新工具。并且逐渐将在工作中实践。在制作窗口雨滴效果,将使用到HAML和Sass。 案例效果 看到上面的效果是不是...
2017-03-29
三步搞定vue在vscode的环境配置问题
1. vscode基础开发插件 vscode-icons 图标美化 Debugger for Chrome 调试 Beautify 代码格式化 Prettier 代码格式化 ESLint 代码规范 JavaScript (ES6) cod...
2017-12-25
vue使用watch 观察路由变化,重新获取内容
问题背景: 点击用户头像 =&gt; 进入用户个人中心,在用户个人中心里点击其他用户的头像,我希望显示被点击用户的个人中心,但只看到了路由参数在发生变化,页面内容并没有更新。如图: 页面代码如下: &lt;script&gt; exp...
2017-03-13
canvas实现流星雨的背景效果
看到一个很棒的流星雨效果。修改一下样式就可以作为网页背景了。。! &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset=&quot;utf-8&quot...
2017-03-09
回到顶部