mpvue小程序仿qq左滑置顶删除

473 阅读5分钟

mpvue仿qq左滑置顶删除组件
背景:

前几天,公司的一个小程序项目开发的时候,遇到了一点点问题。设计师这狗币要让我在小程序上实现类似QQ左滑置顶删除的操作,心里mmp,我就是一个刚来公司三天的小小前端实习生而已,我想学习....当然刚刚来就被公司委以重任,也能看出本人技术过人,尤其是作为一个大二刚刚结束的学生来说。废话不多说,对于这个功能,第一反应就是百度,不百度不得了,一百度吓一跳。前辈们也来都做过。“那我不是直接照搬就行,开心”。开开心心的用mpvue上手之后,心里mmp,mpvue的坑这么多。。。。还不如自己动手撸一个,效率还更快。

image

我们先来看看效果图,有图有真相:

效果图:

image

实现:

1,上面说过mpvue的坑,比如里面的每一个的元素都是overflow:hidden,并且似乎都继承了display:block。(看小程序开发工具是这样的,具体源码没看,就只能猜猜)。所以主要解决是让元素overflow:scroll,这个主要是看效果的时候会用到

2,左滑和右滑,这又是一个坑。本以为mpvue的滑动事件会和vue的一模一样。开开心心的按着原来想法撸,发现怎么滑都滑不动,果断打印一波数据,发现滑动事件大有奥妙!

3,布局方面我采用的是rpx+flex。

4,点击时候置顶与取消置顶是通过json数据的top实现的。删除是用数组的splice()方法。

5,滑动效果是css动画控制的。

下面直接贴代码:如果看不懂可以嫌麻烦可以去我的github:github.com/JB-Chen/mpv…

程序员大佬们,觉得可以就给个star,以资鼓励一下!

HTML代码:

主要的html代码:

<template>  <div class="container">    <!-- 头部 -->    <div class="head">      <img class="userinfo-avatar" v-if="userInfo.avatarUrl" :src="userInfo.avatarUrl" background-size="cover"/>      <span class="head-info">消息</span>    </div>    <!-- 搜索 -->    <div class="search">      <input type="search"/>      <span>搜索</span>    </div>    <!-- 内容 -->    <div class="infoAll" v-for="(item,index) in commitInfo" :key="index">      <ul v-if="item.top">        <li @touchstart="touchStart($event)" @touchend="touchEnd($event,index)" :data-type="item.type" style="background-color:#EDFBFE;">          <div class="imgInfo" @click="recover(index)">            <img :src="item.img">          </div>          <div class="centerInfo">            <div class="name">               <span>{{item.name}}</span>            </div>            <div class="sonName">              <span>{{item.sonName}}</span>              </div>          </div>          <div class="timeInfo" @click="recover(index)">            <div class="time">              <text>{{item.time}}</text>            </div>            <div class="infoNum" style="">                <text style="font-size:12px;">{{item.infoNum}}</text>              </div>          </div>          <div class="top" @click="top(index)" style="width:30%">            取消置顶          </div>        </li>        </ul>    </div>    <div class="infoAll" v-for="(item,index) in commitInfo" :key="index">      <!-- {{item.img}} -->      <ul v-if="!item.top">        <li @touchstart="touchStart($event)" @touchend="touchEnd($event,index)" :data-type="item.type">          <div class="imgInfo" @click="recover(index)">            <img :src="item.img">          </div>          <div class="centerInfo">            <div class="name">               <span>{{item.name}}</span>            </div>            <div class="sonName">              <span>{{item.sonName}}</span>              </div>          </div>          <div class="timeInfo" @click="recover(index)">            <div class="time">              <text>{{item.time}}</text>            </div>            <div class="infoNum" style="">                <text style="font-size:12px;">{{item.infoNum}}</text>              </div>          </div>          <div class="top" @click="top(index)">            置顶          </div>          <div class="delect" @click="delect(index)">            删除          </div>        </li>        </ul>    </div>  </div></template>

css代码:

// 头部*{    margin:0px;    padding: 0px;}.head {    width: 100%;    height:130rpx;    background-color: #38A7FA;    margin-top:-195rpx;    display: flex;    align-items: center;    .head-info{        color: #fff;        font-size:30rpx;        margin-left: 30%;        margin-top:20rpx;        letter-spacing: 4rpx;      }      .userinfo-avatar {        width: 80rpx;        height: 80rpx;        margin: 20rpx;        border-radius: 50%;        margin-top:30rpx;            }  }  .search{      width: 90%;      margin-top:20rpx;      margin-bottom: 20rpx;      input{          width: 100%;          height: 20rpx;          background-color: #F3F3F3;          border-radius: 5rpx;          z-index: 0;      }      span{          position: absolute;          color: #B5B5B5;          font-size: 24rpx;          margin-top:-44rpx;          z-index: 999;          margin-left: 42%;          text-align: center;          }  }  .infoAll{     width: 100%;      ul{        width: 100%;        // overflow-x: scroll;          li{            -webkit-transition: all 0.2s;            transition: all 0.2s;              width: 1100rpx;              height: 150rpx;             //   background-color: red;              line-height: 150rpx;              border-bottom: 1px solid #E0EEF1;            //   垂直居中,  // 子div水平排列              display:flex;            //   justify-content:center;              align-items:center;                          .imgInfo{                width: 100rpx;                height: 100rpx;                border-radius: 50%;                background-color: #38A7FA;                margin-left: 2%;                img{                    width: 100rpx;                    height: 100rpx;                    border-radius: 50%;                    overflow: hidden;                }                              }              .centerInfo{                width: 40%;                height: 150rpx;                margin-left: 2%;                .name{                    margin-top:-20rpx;                    span{                        font-size: 35rpx;                    }                                   }                .sonName{                    margin-top:-110rpx;                    span{                        font-size: 24rpx;                        color: #7C8489;                    }                                }                               }              .timeInfo{                width: 15%;                height: 150rpx;                margin-left: 6%;                               .time{                    margin-top:-20rpx;                    color: #92A0A1;                    font-size: 25rpx;                    position: absolute;                                    }                .infoNum{                    width:50rpx;                    display:flex;                    align-items:center;                    justify-content:center;                    height: 30rpx;                    border-radius: 10rpx;                    background-color: #93D5ED;                    margin-left: 10rpx;                    margin-top: 70rpx;                }                               }              .top{                  width: 15%;                  height: 150rpx;                  background-color: #C4C7CD;                  color: #fff;                  font-size: 34rpx;                  text-align:center              }              .delect{                width: 15%;                height: 150rpx;                background-color: #FF3B32;                color: #fff;                font-size: 34rpx;                text-align:center              }          }      }  }li[data-type="0"]{    transform: translate3d(0,0,0);}li[data-type="1"]{    transform: translate3d(-400rpx,0,0);}

js代码:

<script>import card from '@/components/card'export default {  data () {    return {      userInfo: {},      commitInfo:[        {          img:"http://img3.imgtn.bdimg.com/it/u=3067730600,935028889&fm=27&gp=0.jpg",          name:"旺财",          sonName:"今晚去吃饭吗?",          time:"19:08",          infoNum:"9",          top:false,          type:0        },        {          img:"http://img1.imgtn.bdimg.com/it/u=1257196754,3171363795&fm=27&gp=0.jpg",          name:"前端学习群",          sonName:"hanber:异步与同步的问题",          time:"02:08",          infoNum:"99+",          top:false,          type:0        },        {          img:"https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1672209094,624238697&fm=27&gp=0.jpg",          name:"小学同学",          sonName:"好久不见,最近好吗?",          time:"02:08",          infoNum:"9",          top:false,          type:0        },         {          img:"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1312347818,1612941824&fm=200&gp=0.jpg",          name:"老妈",          sonName:"啥时候回家一趟呀?",          time:"23:08",          infoNum:"1",          top:false,          type:0        },        {          img:"http://img2.imgtn.bdimg.com/it/u=1093392508,3329264726&fm=27&gp=0.jpg",          name:"AD动漫群",          sonName:"ghost:《你的名字》求资源",          time:"02:08",          infoNum:"99+",          top:false,          type:0        }      ]    }  },  components: {    card  },  methods: {  // 滑动开始    touchStart(e){      // 获取移动距离,可以通过打印出e,然后分析e的值得出        this.startX = e.mp.changedTouches[0].clientX;    },    // 滑动结束    touchEnd(e,index){        // 获取移动距离        this.endX = e.mp.changedTouches[0].clientX;          if(this.startX-this.endX > 10){            for(let i=0;i<this.commitInfo.length;i++){                  this.commitInfo[i].type = 0            }            this.commitInfo[index].type = 1        }        else if(this.startX-this.endX < -10){            for(let i=0;i<this.commitInfo.length;i++){                  this.commitInfo[i].type = 0            }        }        },    // 点击回复原状    recover(index){          this.commitInfo[index].type = 0    },    getUserInfo () {      // 调用登录接口      wx.login({        success: () => {          wx.getUserInfo({            success: (res) => {              this.userInfo = res.userInfo            }          })        }      })    },    // 置顶    top(index){      this.commitInfo[index].top = !this.commitInfo[index].top;      this. recover(index);    },    // 删除    delect(index){      this.commitInfo.splice(index,1);    }  },  created () {    // 调用应用实例的方法获取全局数据    this.getUserInfo()  }}</script>