父组件处理:
<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
最好按照官方文档来
开启初始化完毕之后自动执行上拉加载的回调,保证一进入页面,就去加载数据
上拉刷新的时候,或者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)
}
总结
以上所述是小编给大家介绍的vue中的mescroll搜索运用及各种填坑处理,希望对大家有所帮助