Vue实现左右菜单联动实现代码


Posted in Javascript onAugust 12, 2018

本文介绍了Vue实现左右菜单联动实现代码吗,分享给大家,也给自己留个笔记,具体如下:

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 []
 }
 },
}

Vue实现左右菜单联动实现代码

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

Vue实现左右菜单联动实现代码

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打出来看看

Vue实现左右菜单联动实现代码

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

Vue实现左右菜单联动实现代码

所以我们要得到每一块 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)
}

Vue实现左右菜单联动实现代码

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

Vue实现左右菜单联动实现代码

Vue实现左右菜单联动实现代码

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]((https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll 是什么)派发的事件

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

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

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

Javascript 相关文章推荐
深入解析JavaScript中的变量作用域
Dec 06 Javascript
Bootstrap编写一个同时适用于PC、平板、手机的登陆页面
Jun 30 Javascript
将鼠标焦点定位到文本框最后(代码分享)
Jan 11 Javascript
js仿京东轮播效果 选项卡套选项卡使用
Jan 12 Javascript
JavaScript实现弹出广告功能
Mar 30 Javascript
使用vue和datatables进行表格的服务器端分页实例代码
Jun 07 Javascript
bootstrap选项卡扩展功能详解
Jun 14 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
Oct 17 Javascript
vue2.0结合Element-ui实战案例
Mar 06 Javascript
了解JavaScript表单操作和表单域
May 27 Javascript
jQuery实现日历效果
Sep 11 jQuery
JavaScript中的Proxy对象
Nov 27 Javascript
Vue中的v-for循环key属性注意事项小结
Aug 12 #Javascript
vue实现商品加减计算总价的实例代码
Aug 12 #Javascript
Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能
Aug 12 #Javascript
深入理解Vue父子组件生命周期执行顺序及钩子函数
Aug 12 #Javascript
VUE在for循环里面根据内容值动态的加入class值的方法
Aug 12 #Javascript
JS中的两种数据类型及实现引用类型的深拷贝的方法
Aug 12 #Javascript
原生JS封装_new函数实现new关键字的功能
Aug 12 #Javascript
You might like
php巧获服务器端信息
2006/12/06 PHP
PHP防止跨域提交表单
2013/11/01 PHP
php实现按文件名搜索文件的远程文件查找器
2014/05/10 PHP
PHP与MYSQL中UTF8编码的中文排序实例
2014/10/21 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
php利用header函数下载各种文件
2016/08/24 PHP
基于Jquery的$.cookie()实现跨越页面tabs导航实现代码
2011/03/03 Javascript
javascript判断office版本示例
2014/04/11 Javascript
jQuery中:has选择器用法实例
2014/12/30 Javascript
IE7浏览器窗口大小改变事件执行多次bug及IE6/IE7/IE8下resize问题
2015/08/21 Javascript
详解JavaScript对象和数组
2015/12/03 Javascript
js数字舍入误差以及解决方法(必看篇)
2017/02/28 Javascript
浅谈javascript的url参数parse和build函数
2017/03/04 Javascript
通过V8源码看一个关于JS数组排序的诡异问题
2017/08/14 Javascript
在vue中获取token,并将token写进header的方法
2018/09/26 Javascript
ES6知识点整理之模块化的应用详解
2019/04/15 Javascript
Vue开发之封装分页组件与使用示例
2019/04/25 Javascript
express + jwt + postMan验证实现持久化登录
2019/06/05 Javascript
JS中的算法与数据结构之栈(Stack)实例详解
2019/08/20 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
[01:01:41]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第二场 1月31日
2021/03/11 DOTA
python网络编程之UDP通信实例(含服务器端、客户端、UDP广播例子)
2014/04/25 Python
推荐11个实用Python库
2015/01/23 Python
python实现ID3决策树算法
2017/12/20 Python
Python中的枚举类型示例介绍
2019/01/09 Python
Python正则表达式匹配数字和小数的方法
2019/07/03 Python
python保存字典和读取字典的实例代码
2019/07/07 Python
css3 transform及原生js实现鼠标拖动3D立方体旋转
2016/06/20 HTML / CSS
css3实现背景动态渐变效果
2019/12/10 HTML / CSS
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
教师个人自我评价范文
2014/04/13 职场文书
2015年服务员工作总结
2015/04/08 职场文书
公积金贷款承诺书
2015/04/30 职场文书
金砖之国观后感
2015/06/11 职场文书
工作表现证明
2015/06/15 职场文书
入党积极分子培养联系人意见
2015/08/12 职场文书