weex下实现列表项左滑菜单

最近项目中遇到的需求,由于初次接触weex,故做以记录,如有任何不明或错误,欢迎指出。

这里写图片描述

在收货地址的列表的某一项上左滑就显示出该项的编辑和删除菜单。

实现功能

  1. 左滑每一项显示该项的菜单
  2. 在列表中右滑隐藏显示的菜单
  3. 每次只能显示一项的菜单,打开第二项菜单的同时关闭第一项

实现过程

思路是:将每一项的长度设置为页面宽度+300px(1334*750的设计图),即每一项的宽度为1050px。

页面结构如下:

 <scroller class="address__container">
            <div class="address__item" ref="menuItem"  v-for="(item,index) in list" @swipe="slideMenu($event,index)" :key="index" @click="chooseItem(item.id)">
                <div class="address__item__info">
                    <div class="addredd__item__info__top">
                        <text class="fs14 mr4">收货人</text>
                        <text class="fs14 mr4">XXXXXXXX</text>
                        <text class="fs16" style="height:50px;line-height:35px;">131 1313 1313</text>
                    </div>
                    <div class="address__item__info__bottom">
                        <text class="fs12">某某省某某市某某区</text>
                    </div>
                </div>
                <text class="address__item__control">编辑</text>
                <text class="address__item__control address__item__control-delete">删除</text>
            </div>
        </scroller>

关于scroller组件点击这里可以看到官方的文档

每一项的CSS如下:

.address__item {
  width: 1050px;
  height: 170px;
  border-bottom-width: 1px;
  border-bottom-color: @border;
  flex-direction: row;
  flex-wrap: nowrap;
}

现在由于由于页面宽度只有750px,所以有300px被隐藏在右边了,这300px就是我们两个按钮的宽度。

接下来实现左滑显示菜单:

由于当时正在阅读WEEX的官方文档,正好看到了注意: 现在Weex只支持在JavaScript中使用动画, CSS 动画是和JavaScript 动画是不一样的。我们即将支持在CSS中使用动画。、所以我选择了使用weex的内置模块animation来实现动画效果。

关于animation模块点击这里查看。

<div class="address__item" ref="menuItem"  v-for="(item,index) in list" @swipe="slideMenu($event,index)" :key="index" @click="chooseItem(item.id)">

这里调用的weex封装好的手势事件来触发我们的Slide方法。

direction:仅在 swipe 手势中存在,返回滑动方向,返回值可能为 up, left, bottom, right。*

我使用了direction属性来帮助我判断滑动方向,在项目中的体验还可以,准确度较高。

  • 左滑事件:
    @params ele 要执行动画的元素
    leftSlide(ele) {
      animation.transition(
        ele,
        {
          styles: {
            transform: "translateX(-300px)" // 向左移动300px以显示菜单
          },
          duration: 150, //动画持续事件
          timingFunction: "linear",// 动画速度曲线
          needLayout: false, // 节点动画执行时是否产生布局动画即LayoutAnimation
          delay: 0 // 延迟执行动画
        }
      );
    },

右滑事件跟左滑事件相同只是translateX的值为0表示回到原位。

接下来写一个用来判断要滑动的元素以及要滑动方向的方法

 slideMenu(e, index) {
      let listItems = this.$refs.menuItem;
      let ele = this.$refs.menuItem[index];
      let direction = e.direction;
      if (direction == "left") {
        this.leftSlide(ele);
      }else if(direction == "right"){
        this.rightSlide(ele);
      }
    },

调用slideMenu方法的时候传递了 e v e n t i n d e x , i n d e x event中的direction来判断滑动方向,然后调用不同的方法。

现在基本实现了基础的左右滑动事件,但是出现了这样的情况:

所有的菜单都可以同时滑出来

所有的菜单同时展开,看起来很奇怪。

思路大概是这样,打开左滑菜单之前,检查有没有其他的菜单处于打开状态,如果有,关闭该菜单然后再打开当前的菜单。

起初使用this.$refs.menuItem[index].state = 0 || 1 来标识打开状态

然后在执行leftSlide前的时候调用一个方法去遍历所有的menuItem如果state等于1就在该元素上执行右滑操作

后来在实际操作的时候遇到了一些奇怪的问题。于是变换了另一种思路,最终版如下:

将右滑操作改为将所有项translateX(0)。

在执行leftSlide的之前,执行一次rightSlide()方法。

最终的rightSlide():

rightSlide(){
      let listItems = this.$refs.menuItem;
      for (let i = 0; i < listItems.length; i++) {
        animation.transition(
          listItems[i],
          {
            styles: {
              transform: "translateX(0px)"
            },
            duration: 150, //ms
            timingFunction: "linear",
            needLayout: false,
            delay: 0 //ms
          }
        );
      }
      return false;
    }

最终的leftSlide()

    leftSlide(ele) {
      this.rightSlide();
      animation.transition(
        ele,
        {
          styles: {
            transform: "translateX(-300px)"
          },
          duration: 150, //ms
          timingFunction: "linear",
          needLayout: false,
          delay: 0 //ms
        }
      );
    },

最终实现的效果如下

最终滑动效果

对rightSlide()方法对性能的影响尚未做研究,有待商榷。

如有任何错误或不妥之处,欢迎指出。

发布了11 篇原创文章 · 获赞 4 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/kormondor/article/details/79660218