当前位置:主页 > 网页前端 > vue >

vue中的mescroll搜索运用及各种填坑处理

时间:2021-01-28 10:27:08 | 栏目:vue | 点击:

父组件处理:

<template>
    <div class="wrap">
      <!-- 搜索框 -->
      <div class="searchInputArea">
        <div class="searchBarBox">
          <div class="inputWrap" >
            <form onsubmit="javascript:return false" action>
              <input :placeholder = "placeholderStr" type="search" ref = "input" v-model="keyword" />
              <span class="clearBtn" v-show="keyword" @click="clear"></span>   
            </form>  
          </div> 
        </div>
      </div> 
      <div class="myFastChoiceBlock" v-show="!keyword">   
        <!-- 最近伙伴和我的关注 -->
        <fast-choice :successInvite="successInvite" @invite="inviteClick"></fast-choice>
      </div>  
      <div class="searchContainer">      
        <search-content :searchName="keyword" :successInvite="successInvite" @inviteClick="inviteClick" v-if="keyword !== ''"></search-content>
      </div>
       <!-- 协议弹出层 -->
      <pop-up @change="closeLayer" v-if="popuShow">
        <h2 class="title">{{protocolTitle}}</h2>
        <div class="content" v-html="protocolCon"></div>
        <div class="confirmBtn" :class="{active:isActive}" @click="confirmProtocol">{{btntxt}}</div>
        <div class="popCloseCon" @click="closeActionClick"></div>
      </pop-up>
      <!-- 比例弹出层 -->
      <scale @change="closeScale" @send="sendAjaxClick" :number="scaleCount" :scaleBtn="scaleBtn" :scaleDesc="scaleDesc" v-show="isScale" :userId="userId"></scale>
    </div>
</template>
<script>
  import FastChoice from './components/fastChoice';
  import PopUp from './components/PopUp';
  import scale from './components/scale';
  import SearchContent from './components/searchContent';
  const pageSize=10;
  let t='';
  export default {
    name: "Search",
    data() {
      return {
         placeholderStr: '搜一搜你想找的TA',
         keyword: '',
         list: [],
         timerKey: null,
         dataList:[],//列表数据
         totalPage:1,
         popuShow:false,//协议弹出层
         isScale:false,//比例弹出层
         scaleValue:'',//分成比例
         userId:'',
         isActive:true,//操作协议按钮灰色显示
         sencond:5,//秒数
         btntxt:'', //操作协议层按钮文字显示
         scaleValue:'',//分成比例
         scaleDesc:'',//比例弹窗描述
         scaleBtn:'',
         scaleCount:'50%',//默认分成比例
         successInvite: [],//默认未邀请
         protocolTitle:'',//协议标题
         protocolCon:'' //协议内容
      };
    },
    components:{FastChoice,PopUp,scale, SearchContent},
    watch: {
      keyword () {
        if (!this.keyword){
          return;
        }
      }
    },
    mounted() {
      this.protocolAjax(); 
    },
    methods: {
      //邀请
      inviteClick (item) {
       //点击邀请过的不予操作
       if(this.successInvite.indexOf(item.hwUserId) > -1 || item.inviteStatus){
         return;
       }
       this.isScale = true;
       this.userId = item.hwUserId;
       this.scaleDesc = '邀请成功后你可获取该用户部分收益,选择双方都认可的分成比例可以提高邀请成功率哦~';
       this.scaleBtn = '发送邀请';
       this.scaleCount = '50%';//邀请比例统一为50%
      },
      //点击发送邀请
      sendAjaxClick (value){
        this.scaleValue = value;
        this.popuShow = true;
        this.isScale = false;
        this.isActive = true;
        this.sencond = 5 ;
        this.timer();
      },
      //5s时间倒计时
      timer() {
        if (this.sencond > 0) {
          this.btntxt="已阅读同意并确认邀请("+this.sencond+"s)";
          this.sencond--;
          t=setTimeout(this.timer, 1000);     
        } else{
          this.isActive = false;
          this.sencond = 5;
          this.btntxt="已阅读同意并确认邀请";  
        }
      },
      //已阅读同意并确认
      confirmProtocol () {
        if(this.isActive){
          return false;
        }
        this.sendAjax();
      },
      //发送邀请请求
      sendAjax () {
        console.log(this.scaleValue);
        let dd = this.scaleValue.toString();
        this.$request.post(_basePath + '/activity/page20191018/inviteArtist.html',{userId: this.userId,shareRate:this.scaleValue}).then((res) => {
          this.successInvite.push(this.userId) ;
          mui.toast("已发送邀请,对方接受后会通知你哦",2000);
          this.closeActionClick();
        }).catch(() => {})
      },  
      //关闭操作协议弹窗
      closeActionClick() {
        this.popuShow = false;
        clearTimeout(t);//清除倒计时
      },
       //关闭分成比例弹窗
      closeScale () {
        this.isScale = false; 
      },
      clear () {
        this.keyword = "";
        this.$refs["input"].focus();
      },
      protocolAjax () {
         this.$request.post(_basePath + '/activity/page20191018/queryProtocol.html',{type:0}).then((res) => {
         this.protocolTitle = res.title;
         this.protocolCon = res.content;
        }).catch(() => {})
      }
    },
  };
</script>
<style lang="scss" scoped>
 @import "search";
</style>

子组件处理:

<template>
  <div>
    <div ref="mescroll" class="mescroll">
      <div class="search-content wrapper" ref="scroller" > 
        <ul>
          <li class="item" v-for="(item,index) in dataList" :key="index">
            <div class="personBlock" @click="openUserClick(item.userDetail.userId)">
              <div class="showImg">
                <img :src="item.userDetail.userThumUrl" />
                <template v-if="item.userDetail.kolFlag">
                  <em v-if="item.userDetail.kolFlag" class="icon c_kol"></em>
                </template>
                <template v-else>
                  <em class="icon c_company" v-if="item.userDetail.upSignType == '1'"></em>
                  <em class="icon c_person" v-if="item.userDetail.upSignType == '0'"></em>
                </template>
                
              </div>
              <div class="showInfo">
                <div class="name">{{item.userDetail.nickName}}</div>
                <div class="attentionCount">
                  {{item.userDetail.fansCount || 0}}人关注TA
                </div>
              </div>
            </div>
            <div class="sendBtn" :class="{active:item.userDetail.inviteStatus || (successInvite.indexOf(item.userDetail.hwUserId) > -1 ) }" @click="inviteClick(item.userDetail)">
              <span v-if="item.userDetail.inviteStatus || successInvite.indexOf(item.userDetail.hwUserId) > -1">已邀请</span>
              <span v-else>邀请</span>
            </div>
          </li> 
        </ul> 
        
      </div>
    </div>
    <empty v-show="isEmpty">
      <p class="note">纳尼,竟然找不到这个人…</p>
    </empty>
  </div>  
</template>

<script>
import MeScroll from 'mescroll.js';
import 'mescroll.js/mescroll.min.css';
import Empty from './empty';
 const pageSize=10;
export default {
  name: 'SearchContent',
  props: {
    searchName: {
      type: String,
      default: ''
    },
    successInvite: {
      type: Array,
      default: []
    }
  },
  data() {
    return {
      dataList: [],
      mescroll: null, //mescroll实例对象
      totalPage:1,
      isEmpty:false
    }
  },
  components:{
    Empty 
  },
  watch: {
    'searchName' () {
      this.dataList = [];//要清空,不然有时候会出现上拉加载不了
      this.searchName !== '' && this.mescroll.resetUpScroll();
    }
  },
  mounted () {
    console.log(this.searchName)
    this.mescroll = new MeScroll(this.$refs.mescroll, { //在mounted初始化mescroll,确保此处配置的ref有值
      down:{isLock: true}, //下拉刷新的配置. (如果下拉刷新和上拉加载处理的逻辑是一样的,则down可不用写了)            
      up: {
          callback: this.upCallback,
          // 以下是一些常用的配置,当然不写也可以的.
          page: {
            num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
            size: 10, //每页数据条数,默认10
          },
          htmlLoading: '<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">正在加载中..</p>',
          htmlNodata: '<p class="upwarp-nodata" style="height:.4rem">当当当~已经到底啦~</p>',
          noMoreSize: 1, //如果列表已无数据,可设置列表的总数量要大于5才显示无更多数据;
          isBounce: true,
      },
      down:{
        use:false
      },
    });
  },
  methods: {
     //点击调起个人主页
    openUserClick (item) {
      console.log(item)
      var userId = item;
       mui.openClient({"pageType": "userHome","userId":item});
    },
     //上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10
    upCallback(page) {
      //联网请求
      this.$request.post(_basePath + '/activity/page20191018/searchAll.html', {hintKey:this.searchName,searchType:91,pageNo:page.num,pageSize:page.size,actionSource:'07'}).then((response) => {
          if(response && response.resultList){
           // 请求的列表数据
            let result = response.resultList[0];
            let arr = result.list;
            // 如果是第一页需手动置空列表
            if (page.num === 1) this.dataList = []
            // 把请求到的数据添加到列表
            this.dataList = this.dataList.concat(arr)
            // 数据渲染成功后,隐藏下拉刷新的状态
            this.totalPage = result.total % pageSize > 0 ? Math.floor(result.total / 10 + 1) : result.total / 10;//计算总页数超过就不loadMore
            this.$nextTick(() => {
                this.mescroll.endSuccess(arr.length);
                this.mescroll.endByPage(arr.length, this.totalPage)
            }) 
          }else{
            this.isEmpty = true;
            this.mescroll.endErr();
          }          
      }).catch(() => {
          this.mescroll.endErr();
      })
    },
    inviteClick(item) {
      this.$emit('inviteClick',item);
    }
}

}
</script>

<style lang="scss" scoped>
.mescroll {
  position: fixed;
  top: .9rem;
  bottom: 0;
  left:0;
  height: auto;
}
.search-content{
  padding:0 .24rem; 
  background: #121223;
  ul{
    height:auto;
    .item{
      display:flex;
      justify-content:space-between;
      align-items:center;
      width:100%;
      height:1.56rem;
      .personBlock{
        display:flex;
        justify-content: flex-start;
        align-items: center;
        .showImg{
          position:relative;
          width:1rem;
          height:1rem;
          margin-right:.16rem;
          border:.02rem solid #51516D;
          border-radius:50%;
          box-sizing: border-box;
          img{width:100%;height:100%;border-radius:50%}
          .icon{
            position: absolute;
            bottom:0;
            right:0;
            width:.28rem;
            height:.28rem;
            background-image:url();
            background-repeat:no-repeat;
            background-size:contain;
            &.c_company{background-image:url(../../images/c_company.png);}
            &.c_person{background-image:url(../../images/c_person.png);}
            &.c_kol{background-image:url(../../images/kol.png);}
          }
        }
        .showInfo{
          .name{font-size:.3rem;color:#fff;font-weight:500;line-height:.42rem;text-align:left;}
          .attentionCount{font-size:.26rem;font-weight:400;color:#716D80;text-align:left;}
        }
      }
      
      .sendBtn{
        width:1.44rem;
        height:.56rem;
        line-height:.56rem;
        background:#FF005E;
        border-radius:.28rem;
        color:#fff;
        text-align:center;
        &.active{background:#2C2B41;color:#fff}
      }
    }
  }
}  

</style>

填坑处理:

1、用户未输入搜索关键词时,mescroll不能就直接初始话,要在用户输入的时候才能初始化,所以子组件就接受了父组件的keyword,并用

v-if="keyword !== ''"来判断加载子组件的条件,然后子组件通过监听keyword的变化,重置mescroll:如下:

watch: {
    'searchName' () {
      this.dataList = [];//要清空,不然有时候会出现上拉加载不了
      this.searchName !== '' && this.mescroll.resetUpScroll();
    }
  },

  2、搜索完以后点击搜索输入框右边里的关闭按钮,发现其他列表不能滑动。解决方法:要加:isBounce: true,

ps:下面看下mescroll vue使用

github: https://github.com/mescroll/mescroll

官方文档:http://www.mescroll.com

最好按照官方文档来

开启初始化完毕之后自动执行上拉加载的回调,保证一进入页面,就去加载数据

上拉刷新的时候,或者tab切换的时候,先将数据置空

page 和 pageSize使用upOption中的,并且num默认为0

代码:

// html
<mescroll-uni top="100" @down="downCallback" @up="upCallback" @init="mescrollInit" :up="upOption" :down="downOption">

//data:
// 下拉刷新的常用配置
downOption: {
 use: true, // 是否启用下拉刷新; 默认true
 auto: false, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
},
// 上拉加载的常用配置
upOption: {
 use: true, // 是否启用上拉加载; 默认true
 auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
 textNoMore:'我是有底线的 >_<',
 page: {
 num:0,
 size: 4
 }
},
list:[],

//methods:
// 下拉回调
downCallback(mescroll){
 mescroll.setPageNum(1)
 this.list = []
 mescroll.resetUpScroll(); 
 setTimeout(()=>{
 console.log(666);
 // 隐藏下拉加载状态
 mescroll.endErr()
 },1000)
},
// 上拉回调
upCallback(mescroll){
 setTimeout(()=>{
 let pageNum = mescroll.num == 0 ? 1: mescroll.num; // 页码, 默认从1开始
 let pageSize = mescroll.size;
 this.getPageList(pageNum, pageSize).then((res)=>{
  mescroll.endSuccess(res)
 })
 },1000)
}

总结

您可能感兴趣的文章:

相关文章