WXDropDownMenu-小程序下拉菜单,可用于筛选

[复制链接]
haoyangtian实名认证 手机认证 视频认证 发表于 2017-5-16 21:10:28 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

思路与步骤:


153914hatyd8116as316y3.gif

布局方面,整体使用dl来写,二级包在dd中,用ul li来写;交互方面,点击某一级菜单,关闭兄弟子菜单,点击某子菜单关闭所有菜单。

1.使用dt做出第一级菜单

2.使用dd嵌套第二级菜单,初始隐藏、position为absolute,使用z-index浮出页面层

  1. /*总菜单容器*/
  2. .menu {
  3.     display: block;
  4.     height: 38px;
  5. }

  6. /*一级菜单*/
  7. .menu dt {
  8.     font-size: 15px;
  9.     float: left;
  10.     /*hack*/
  11.     width: 33%;
  12.     height: 38px;
  13.     border-right: 1px solid #d2d2d2;
  14.     border-bottom: 1px solid #d2d2d2;
  15.     text-align: center;
  16.     background-color: #f4f4f4;
  17.     color: #5a5a5a;
  18.     line-height: 38px;
  19. }

  20. /*二级菜单外部容器样式*/
  21. .menu dd{
  22.     position: absolute;
  23.     width: 100%;
  24.     /*hack*/
  25.     top:39px;
  26.     left:0;
  27.     z-index:999;
  28. }

  29. /*二级菜单普通样式*/
  30. .menu li{
  31.     font-size: 14px;
  32.     line-height: 34px;
  33.     color: #575757;
  34.     height: 34px;
  35.     display: block;
  36.     padding-left: 8px;
  37.     background-color: #fff;
  38.     border-bottom: 1px solid #dbdbdb;
  39. }
复制代码
查看效果,接下来实现点击事件。

如图

153916gb8s0p0kmqh0ws30.png


3.dt绑定点击事件tapMainMenu,flag控制显隐toggle,提供2个class,hidden与show,来控制显隐。注:dt也是可以bindTap的,不单是view。

  1. /* 显示与隐藏 */
  2. .show {
  3.     display: block;
  4. }

  5. .hidden {
  6.     display: none;
  7. }
复制代码

4.关闭所有一级菜单,每个一级菜单都有一个index标识,由tapMainMenu事件传递过去,与数组subMenuDisplay一一对应,当前元素subMenuDisplay[index]视原来状态决定是显示或隐藏。

核心代码:

  1. <dl class="menu">
  2.     <dt data-index="0" bindtap="tapMainMenu">价格</dt>
  3.     <dd class="{{subMenuDisplay[0]}}">
  4.         <ul><li>sub1</li><li>sub2</li></ul>
  5.     </dd>
  6. </dl>
复制代码
  1. // 使用function初始化array,相比var initSubMenuDisplay = [] 既避免的引用复制的,同时方式更灵活,将来可以是多种方式实现,个数也不定的
  2. function initSubMenuDisplay() {
  3.     return ['hidden', 'hidden', 'hidden'];
  4. }

  5. Page({
  6.     data:{
  7.         subMenuDisplay:initSubMenuDisplay()
  8.     },
  9.     tapMainMenu: function(e) {
  10. //      获取当前显示的一级菜单标识
  11.         var index = parseInt(e.currentTarget.dataset.index);
  12.         // 生成数组,全为hidden的,只对当前的进行显示
  13.         var newSubMenuDisplay = initSubMenuDisplay();
  14. //      如果目前是显示则隐藏,反之亦反之。同时要隐藏其他的菜单
  15.         if(this.data.subMenuDisplay[index] == 'hidden') {
  16.             newSubMenuDisplay[index] = 'show';
  17.         } else {
  18.             newSubMenuDisplay[index] = 'hidden';
  19.         }
  20.         // 设置为新的数组
  21.         this.setData({
  22.             subMenuDisplay: newSubMenuDisplay
  23.         });
  24.     }
  25. });
复制代码

5.选中二级菜单当前项,但给个系统icon及改变背景色,文本加粗,同样改变一级菜单标题,demo中给出一个弹窗

声明tapSubMenu方法,监听二级点击事件

  1. tapSubMenu: function(e) {
  2.         //      获取当前显示的一级菜单标识
  3.         var index = parseInt(e.currentTarget.dataset.index);
  4.         console.log(index);
  5.         // 隐藏所有一级菜单
  6.         this.setData({
  7.             subMenuDisplay: initSubMenuDisplay()
  8.         });
  9.     }
复制代码

加highlight效果

  1. /*二级菜单高亮样式*/
  2. .menu li.highlight{
  3.     background-color: #f4f4f4;
  4. }
复制代码

与一级菜单不同,使用二维数组的方式实现点击高亮,这样才能定位到是某一级的某二级菜单,再决定显示隐藏。 布局文件改成:

  1. <dd class="{{subMenuDisplay[0]}}">
  2.         <ul>
  3.             <li class="{{subMenuHighLight[0][0]}}" data-index="0-0" bindtap="tapSubMenu">100以内</li>
  4.             <li class="{{subMenuHighLight[0][1]}}" data-index="0-1" bindtap="tapSubMenu">100-500</li>
  5.             <li class="{{subMenuHighLight[0][2]}}" data-index="0-2" bindtap="tapSubMenu">500-1000</li>
  6.             <li class="{{subMenuHighLight[0][3]}}" data-index="0-3" bindtap="tapSubMenu">1000-3000</li>
  7.             <li class="{{subMenuHighLight[0][4]}}" data-index="0-4" bindtap="tapSubMenu">3000以上</li>
  8.         </ul>
  9.     </dd>
复制代码

效果如图

153916gb8s0p0kmqh0ws30.png

相应的js代码要写成:

  1. //声明初始化高亮状态数组
  2. function initSubMenuHighLight() {
  3.     return [
  4.         ['','','','',''],
  5.         ['',''],
  6.         ['','','']
  7.     ];
  8. }
复制代码

点击事件

  1. tapSubMenu: function(e) {
  2.         // 隐藏所有一级菜单
  3.         this.setData({
  4.             subMenuDisplay: initSubMenuDisplay()
  5.         });
  6.         // 处理二级菜单,首先获取当前显示的二级菜单标识
  7.         var indexArray = e.currentTarget.dataset.index.split('-');
  8.         console.log("indexArray : " + indexArray);
  9.         var newSubMenuHighLight = initSubMenuHighLight();
  10.         // 与一级菜单不同,这里不需要判断当前状态,只需要点击就给class赋予highlight即可
  11.         newSubMenuHighLight[indexArray[0]][indexArray[1]] = 'highlight';
  12.         console.log(newSubMenuHighLight);
  13.         // 设置为新的数组
  14.         this.setData({
  15.             subMenuHighLight: newSubMenuHighLight
  16.         });
  17.     }
复制代码

这样就实现了高亮与取消高亮。但还没完,与一级菜单不同,这里与兄弟子菜单是非互斥的,也就是说点击了本菜单,是不能一刀切掉兄弟菜单的高亮状态的。于是我们改进js代码。


声明方式,改用变量形式,方便存储。

  1. //定义初始化数据,用于运行时保存
  2. var initSubMenuHighLight = [
  3.         ['','','','',''],
  4.         ['',''],
  5.         ['','','']
  6.     ];
复制代码

点击事件

  1. tapSubMenu: function(e) {
  2.         // 隐藏所有一级菜单
  3.         this.setData({
  4.             subMenuDisplay: initSubMenuDisplay()
  5.         });
  6.         // 处理二级菜单,首先获取当前显示的二级菜单标识
  7.         var indexArray = e.currentTarget.dataset.index.split('-');
  8.         // 初始化状态
  9.         // var newSubMenuHighLight = initSubMenuHighLight;
  10.         for (var i = 0; i < initSubMenuHighLight.length; i++) {
  11.             // 如果点中的是一级菜单,则先清空状态,即非高亮模式,然后再高亮点中的二级菜单;如果不是当前菜单,而不理会。经过这样处理就能保留其他菜单的高亮状态
  12.             if (indexArray[0] == i) {
  13.                 for (var j = 0; j < initSubMenuHighLight[i].length; j++) {
  14.                     // 实现清空
  15.                     initSubMenuHighLight[i][j] = '';
  16.                 }
  17.                 // 将当前菜单的二级菜单设置回去
  18.             }
  19.         }

  20.         // 与一级菜单不同,这里不需要判断当前状态,只需要点击就给class赋予highlight即可
  21.         initSubMenuHighLight[indexArray[0]][indexArray[1]] = 'highlight';
  22.         // 设置为新的数组
  23.         this.setData({
  24.             subMenuHighLight: initSubMenuHighLight
  25.         });
  26.     }
复制代码
有待完善功能点:

1.显示与隐藏带动画下拉

2.抽象化,使用回调函数,将1监听每个二级菜单的点击

3.数据源与显示应当是分离的,一级与二级菜单的key value应该是独立在外,系统只认index,然后对相应点击作处理,跳转页面,筛选结果等

[2016-10-18]

官方文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-animation.html

153914hatyd8116as316y3.gif


改为动画版,需要要满足平移动画与背景遮罩。思路如下:

1.二级菜单初始隐藏且位置位于手机屏幕之外

2.当点击一级菜单时,二级菜单平移向下,直到二级菜单上边缘与一级菜单下边缘平齐。使用linear动画

3.点击自身或其他一级菜单,做逆操作

4.背景遮罩,使用ease-in/ease-out动画

步骤1 改造样式表,top值

步骤2 声明动画

核心代码:

  1. animation: function(index) {
  2.         // 定义一个动画
  3.         var animation = wx.createAnimation({
  4.             duration: 400,
  5.             timingFunction: 'linear',
  6.         })
  7.         // 是显示还是隐藏
  8.         var flag = this.data.subMenuDisplay[index] == 'show' ? 1 : -1;
  9.         // flag = 1;
  10.         console.log(flag)
  11.         // 使之Y轴平移
  12.         animation.translateY(flag * (initSubMenuHighLight[index].length * 34) + 8).step();
  13.         // 导出到数据,绑定给view属性
  14.         this.setData({
  15.             animationData:animation.export()
  16.         });
  17.     }
复制代码
完成动画后,需调用一次step(),不论是一组还是多组都需要调。

步骤3 声明data数组并与wxml绑定

  1. animationData: {}
复制代码

wxml中

  1. <dd animation="{{animationData}}">
复制代码
z-index问题,会挡住一级菜单,设置为-999,可以置于一级菜单之下

使用bottom: 0;初始在一级菜单底边缘平齐。

dl 设置为position: relative; 与二级菜单 position: absolute 对应。

步骤4 点击一级菜单调用动画

  1. // 设置动画
  2.         this.animation(index);
复制代码

步骤5 点击二级菜单调用动画

  1. // 设置动画
  2.         this.animation(indexArray[0]);
复制代码

步骤6 display属性要改为visibility

  1. /* 显示与隐藏 */
  2. .show {
  3.     /*display: block;*/
  4.     visibility: visible;
  5. }

  6. .hidden {
  7.     /*display: none;*/
  8.     visibility:hidden;
  9. }
复制代码
保留占位,宽度高度,不然点击没了动画效果。

项目下载地址:

游客,如果您要查看本帖隐藏内容请回复


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

专注源码分享,教程分享
全国服务电话

187-8198-7163

周一至周8:00-22:00

反馈建议

cdhaoyt@163.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.2© 2001-2013 Comsenz Inc.( 蜀ICP备16032957号-1