最近项目中遇到的需求,由于初次接触weex,故做以记录,如有任何不明或错误,欢迎指出。
在收货地址的列表的某一项上左滑就显示出该项的编辑和删除菜单。
实现功能
- 左滑每一项显示该项的菜单
- 在列表中右滑隐藏显示的菜单
- 每次只能显示一项的菜单,打开第二项菜单的同时关闭第一项
实现过程
思路是:将每一项的长度设置为页面宽度+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方法的时候传递了 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()方法对性能的影响尚未做研究,有待商榷。
如有任何错误或不妥之处,欢迎指出。