vue滚动+滑动删除标记(移动端)仿qq/微信

安装组件
  "vue-touch": "^2.0.0-beta.4",
main.js引入
  import VueTouch from 'vue-touch'
  Vue.use(VueTouch, {name: 'v-touch'})
1.页面代码
<template>
    <div class="share">
      <headall :appMenuName="$t('pay_attention_to_people')" :iconRight="iconRight" :backUrl="backUrl" @backOperate="backOperate"></headall>
      <scroll class="scroll" :data='listData' v-if='listData'>
        <div class="in-ul">
          <div class="item" v-for='(item,index) in listData' :key="index">
            <v-touch v-on:swipeleft="swiperleft(index)" v-on:swiperight="swiperright(index)" class="wrapper">
              <div class="itemSwipe" :class="{swipeleft:itemTitleLeft&&(nowControlIndex==index&&(nowControlIndex>-1)),swipeleftNo:!itemTitleLeft}">
                <div class="content">
                  <span class="userNameAccount">{{ item.userName }}({{item.account}})</span>
                  <span class="deptName">{{ item.deptName||''}}</span>
                </div>
                <div class="btnL del" @click="delUser(item)">删除</div>
                <div class="btnL markEle">标记</div>
                <div class="btnL move">移动</div>
              </div>
            </v-touch>
          </div>
        </div>
      </scroll>
      <router-view @getRefresh="getRefresh"></router-view>
    </div>
</template>

<script>
    import Vue from 'vue'
    import headall from 'base/head/headAll'
    import {
        mixins
    } from 'assets/js/mixins'
    import scroll from 'base/scroll/scroll'
    import i18n from 'assets/js/vi18n/i18n.js'
    export default {
        mixins: [mixins],
        i18n,
        data() {
            return {
                searchVal:'',
                listData: [],
                selectItemData: null,
                nowControlIndex:-1,
                itemTitleLeft:false,
                backUrl:'/me/person',
                iconRight:'icon-tianjia',
            }
        },
        components: {
            headall,
            scroll,
        },
        methods: {
            getRefresh(){
              this.getSelectedUser();
            },
            backOperate(){
              this.$router.push({
                path: `/me/person/attention/add`
              }); 
              //清除滑动效果
              this.itemTitleLeft = false;
              this.nowControlIndex = -1;
            },
            swiperleft(index) {
                //左滑
                console.log('left');
                this.nowControlIndex = index;
                this.itemTitleLeft = true;
            },
            swiperright(index) {
                //右滑
                console.log('right');
                this.itemTitleLeft = false;
                this.nowControlIndex = -1;
            },
            getSelectedUser() {
              /*获取邮件接收人以前的设置*/
              let vm = this;
              let getUserUrl = '/user/focusUsers';
              this.ajaxSend(getUserUrl, {}).then(function (data) {
                if (data.code === '00000000') {
                  vm.listData = data.payload.results.users;
                }
              });
            },
            delUser(item) {
              /*列表中删除关注人*/
              let vm = this;
              let result = [];
              let arr = vm.listData;
              for (let i = 0; i < arr.length; i++) {
                if (arr[i] != item) {
                  result.push(arr[i]);
                }
              }
              vm.listData = result;
              vm.saveSelectedUser();
              //清除滑动效果
              vm.itemTitleLeft = false;
              vm.nowControlIndex = -1;
            },
            saveSelectedUser() {
              //保存设置
              let vm = this;
              let arr = vm.listData;
              let checkedId = [];
              for (let i = 0; i < arr.length; i++) {
                checkedId.push(arr[i].id);
              }
              let getUserUrl = '/user/saveFocusUser';
              let params = {
                focusUserIds: checkedId
              };
              this.ajaxSend(getUserUrl, params).then(function (data) {
                if (data.code === '00000000') {
                }
              });
            },
        },
        created() {
            this.getSelectedUser();
        },
    }
</script>

<style scoped lang="stylus">
@import '~assets/stylus/veriable.styl'
@import "~assets/stylus/mixin.styl"
 .share{
    position absolute
    top 0
    bottom 0
    left 0
    right 0
    z-index 15
    background #f3f3f3
    .scroll{
      position absolute
      overflow hidden
      width 100%
      top 3.2rem
      bottom 0
      background #fff
      .in-ul{
        width 100%
        .item{
            width 146%
            overflow hidden
            .itemSwipe{
              display flex
              flex 1
              font-size .875rem
              height 3rem
              line-height 3rem
              background #fff
              border-bottom 1px solid #dedfe0
              div{
                  background #fff
              }
              .content{
                  width 100%
                  display flex
                  flex-direction column
                  margin .25rem .25rem .25rem .5rem
                  line-height 1.5rem
                  font-size $font-size12
                  .userNameAccount{
                    font-size $font-size13
                  }
                  .deptName{
                    font-size $font-size12
                    color #999
                  }
                  
              }
              .btnL{
                  padding 1rem 0;
                  line-height 1rem
                  width 15%
                  text-align center
                  color #fff
              }
              .del{
                  background #ff3b30
              } 
              .markEle{
                  background #ff9c00
              }
              .move{
                  background #c7c7cc
              }
            }
            .swipeleft{
                transform:translateX(-31%);
                -webkit-transform:translateX(-31%);
                -webkit-transition:all 0.3s;transition:all 0.3s;
            }
            .swipeleftNo{
                -webkit-transition:all 0.3s;transition:all 0.3s;
            }
        }
      }
    }
 }

</style>
组件headAll
<
template> <div class="header"> <span class="iconfont" :class="iconLeft" @click="back"></span> <span class="name" slot="appMenuName">{{appMenuName}}</span> <span class="iconfont" :class="iconRight" @click="search"></span> </div> </template> <script> export default { props:{ appMenuName:{ type:String, default:'', }, backUrl:{ type:String, default:'', }, iconLeft:{ type:String, default:'icon-fanhui1', }, iconRight:{ type:String, default:'icon-soushuo', }, typeVal:{ type:Number, default: 0, }, }, methods: { back(){ this.$router.push({ path: `${this.backUrl}` }); }, search(){ this.$emit('backOperate',this.typeVal); } } } </script> <style scoped lang='stylus'> @import '~assets/stylus/veriable.styl' @import '~assets/stylus/mixin.styl' .header{ headStyle() justify-content space-between .name{ font-size $font-size15 } .iconfont{ padding 0.625rem width 3rem color #bfbfbf font-size .875rem font-weight normal } } </style>
组件scroll
<
template> <div ref="wrapper"> <slot></slot> </div> </template> <script> import BScroll from 'better-scroll' export default { props:{ /* probeType的作用。 1 滚动的时候会派发scroll事件,会截流,就是不会实时的派发。 2 滚动的时候会实时派发scroll事件,不会被截流。 3 在重击的情况下仍然能实时派发scroll的事件。 */ probeType:{ type:Number, default:3 }, click:{ // 占击滚动的列表是否派发click事件。 type:Boolean, default:true }, scrollX:{ // 是否派发横向滚动事件。 type:Boolean, default:false }, listenScroll:{ // 是否派发滚动事件。 type:Boolean, default:true }, data:{ type:Array, default:null //这里null其实是表明这个是一个任意类型。 }, pullup:{ // 是否派发滚动到底部的事件,用于上拉加载 type:Boolean, default:false }, pulldown:{ // 是否派发顶部下拉的事件,用于下拉刷新。 type:Boolean, default:false }, beforeScroll:{ // 是否派发列表滚动开始时的事件。 type:Boolean, default:false }, refreshDelay:{ // 当数据更新后刷新scroll的延时。 type:Number, default:20 }, scrollEndx:{ type:Boolean, default:false } }, methods:{ _initScroll(){ if(!this.$refs.wrapper){ return } // 初始化better-scroll this.scroll=new BScroll(this.$refs.wrapper,{ probeType:this.probeType, click:this.click, scrollX:this.scrollX }) // 是否派发滚动事件。 if(this.listenScroll){ this.scroll.on('scroll',(pos)=>{ this.$emit('scroll',pos); }) } // 是否派发滚动到底部的事件,用于上拉加载。 if(this.pullup){ this.scroll.on('scrollEnd',()=>{ if(this.scroll.y<=(this.scroll.maxScrollY+50)){ this.$emit('scrollEnd'); } }) } // 是否派发顶部下拉事件,用下下拉刷新。 if(this.pulldown){ this.scroll.on('touchend',(pos)=>{ if(pos.y>50){ this.$emit('pulldown') } }) } // 是否派发列表滚动开始的事件。 if(this.beforeScroll){ this.scroll.on('beforeScrollStart',()=>{ this.$emit('beforeScroll') }) } // 新增一个事件的判断,滚动结束时也会触发事件scrollEnd if(this.scrollEndx){ this.scroll.on('scrollEnd',(pos)=>{ this.$emit("scrollEnd",pos); }) } }, refresh(){ this.scroll && this.scroll.refresh(); }, scrollTo(){ this.scroll && this.scroll.scrollTo.apply(this.scroll,arguments); }, scrollToElement(){ this.scroll && this.scroll.scrollToElement.apply(this.scroll,arguments); } }, watch:{ data(){ setTimeout(() => { this.refresh(); }, this.refreshDelay); } }, mounted () { // mouted全部挂载完成后,调用初始化BScroll; setTimeout(() => { this._initScroll(); }, 20); } } </script> <style scoped lang="stylus" rel="stylesheet/stylus"> </style>
原文地址:https://www.cnblogs.com/cx709452428/p/10119856.html