父组件处理:
1 <template> 2 <div class="wrap"> 3 <!-- 搜索框 --> 4 <div class="searchinputarea"> 5 <div class="searchbarbox"> 6 <div class="inputwrap" > 7 <form onsubmit="javascript:return false" action> 8 <input :placeholder = "placeholderstr" type="search" ref = "input" v-model="keyword" /> 9 <span class="clearbtn" v-show="keyword" @click="clear"></span> 10 </form> 11 </div> 12 </div> 13 </div> 14 <div class="myfastchoiceblock" v-show="!keyword"> 15 <!-- 最近伙伴和我的关注 --> 16 <fast-choice :successinvite="successinvite" @invite="inviteclick"></fast-choice> 17 </div> 18 <div class="searchcontainer"> 19 <search-content :searchname="keyword" :successinvite="successinvite" @inviteclick="inviteclick" v-if="keyword !== ''"></search-content> 20 </div> 21 <!-- 协议弹出层 --> 22 <pop-up @change="closelayer" v-if="popushow"> 23 <h2 class="title">{{protocoltitle}}</h2> 24 <div class="content" v-html="protocolcon"></div> 25 <div class="confirmbtn" :class="{active:isactive}" @click="confirmprotocol">{{btntxt}}</div> 26 <div class="popclosecon" @click="closeactionclick"></div> 27 </pop-up> 28 <!-- 比例弹出层 --> 29 <scale @change="closescale" @send="sendajaxclick" :number="scalecount" :scalebtn="scalebtn" :scaledesc="scaledesc" v-show="isscale" :userid="userid"></scale> 30 </div> 31 </template> 32 33 <script> 34 import fastchoice from './components/fastchoice'; 35 import popup from './components/popup'; 36 import scale from './components/scale'; 37 import searchcontent from './components/searchcontent'; 38 const pagesize=10; 39 let t=''; 40 export default { 41 name: "search", 42 data() { 43 return { 44 placeholderstr: '搜一搜你想找的ta', 45 keyword: '', 46 list: [], 47 timerkey: null, 48 datalist:[],//列表数据 49 totalpage:1, 50 popushow:false,//协议弹出层 51 isscale:false,//比例弹出层 52 scalevalue:'',//分成比例 53 userid:'', 54 isactive:true,//操作协议按钮灰色显示 55 sencond:5,//秒数 56 btntxt:'', //操作协议层按钮文字显示 57 scalevalue:'',//分成比例 58 scaledesc:'',//比例弹窗描述 59 scalebtn:'', 60 scalecount:'50%',//默认分成比例 61 successinvite: [],//默认未邀请 62 protocoltitle:'',//协议标题 63 protocolcon:'' //协议内容 64 }; 65 }, 66 components:{fastchoice,popup,scale, searchcontent}, 67 watch: { 68 keyword () { 69 if (!this.keyword){ 70 return; 71 } 72 } 73 }, 74 mounted() { 75 this.protocolajax(); 76 }, 77 methods: { 78 //邀请 79 inviteclick (item) { 80 //点击邀请过的不予操作 81 if(this.successinvite.indexof(item.hwuserid) > -1 || item.invitestatus){ 82 return; 83 } 84 this.isscale = true; 85 this.userid = item.hwuserid; 86 this.scaledesc = '邀请成功后你可获取该用户部分收益,选择双方都认可的分成比例可以提高邀请成功率哦~'; 87 this.scalebtn = '发送邀请'; 88 this.scalecount = '50%';//邀请比例统一为50% 89 }, 90 //点击发送邀请 91 sendajaxclick (value){ 92 this.scalevalue = value; 93 this.popushow = true; 94 this.isscale = false; 95 this.isactive = true; 96 this.sencond = 5 ; 97 this.timer(); 98 }, 99 //5s时间倒计时 100 timer() { 101 if (this.sencond > 0) { 102 this.btntxt="已阅读同意并确认邀请("+this.sencond+"s)"; 103 this.sencond--; 104 t=settimeout(this.timer, 1000); 105 } else{ 106 this.isactive = false; 107 this.sencond = 5; 108 this.btntxt="已阅读同意并确认邀请"; 109 } 110 }, 111 //已阅读同意并确认 112 confirmprotocol () { 113 if(this.isactive){ 114 return false; 115 } 116 this.sendajax(); 117 }, 118 //发送邀请请求 119 sendajax () { 120 console.log(this.scalevalue); 121 let dd = this.scalevalue.tostring(); 122 this.$request.post(_basepath + '/activity/page20191018/inviteartist.html',{userid: this.userid,sharerate:this.scalevalue}).then((res) => { 123 this.successinvite.push(this.userid) ; 124 mui.toast("已发送邀请,对方接受后会通知你哦",2000); 125 this.closeactionclick(); 126 }).catch(() => {}) 127 }, 128 //关闭操作协议弹窗 129 closeactionclick() { 130 this.popushow = false; 131 cleartimeout(t);//清除倒计时 132 }, 133 //关闭分成比例弹窗 134 closescale () { 135 this.isscale = false; 136 }, 137 clear () { 138 this.keyword = ""; 139 this.$refs["input"].focus(); 140 }, 141 protocolajax () { 142 this.$request.post(_basepath + '/activity/page20191018/queryprotocol.html',{type:0}).then((res) => { 143 this.protocoltitle = res.title; 144 this.protocolcon = res.content; 145 }).catch(() => {}) 146 } 147 }, 148 }; 149 </script> 150 151 <style lang="scss" scoped> 152 @import "search"; 153 </style>
子组件处理:
1 <template> 2 <div> 3 <div ref="mescroll" class="mescroll"> 4 <div class="search-content wrapper" ref="scroller" > 5 <ul> 6 <li class="item" v-for="(item,index) in datalist" :key="index"> 7 <div class="personblock" @click="openuserclick(item.userdetail.userid)"> 8 <div class="showimg"> 9 <img :src="item.userdetail.userthumurl" /> 10 <template v-if="item.userdetail.kolflag"> 11 <em v-if="item.userdetail.kolflag" class="icon c_kol"></em> 12 </template> 13 <template v-else> 14 <em class="icon c_company" v-if="item.userdetail.upsigntype == '1'"></em> 15 <em class="icon c_person" v-if="item.userdetail.upsigntype == '0'"></em> 16 </template> 17 18 </div> 19 <div class="showinfo"> 20 <div class="name">{{item.userdetail.nickname}}</div> 21 <div class="attentioncount"> 22 {{item.userdetail.fanscount || 0}}人关注ta 23 </div> 24 </div> 25 </div> 26 <div class="sendbtn" :class="{active:item.userdetail.invitestatus || (successinvite.indexof(item.userdetail.hwuserid) > -1 ) }" @click="inviteclick(item.userdetail)"> 27 <span v-if="item.userdetail.invitestatus || successinvite.indexof(item.userdetail.hwuserid) > -1">已邀请</span> 28 <span v-else>邀请</span> 29 </div> 30 </li> 31 </ul> 32 33 </div> 34 </div> 35 <empty v-show="isempty"> 36 <p class="note">纳尼,竟然找不到这个人…</p> 37 </empty> 38 </div> 39 </template> 40 41 <script> 42 import mescroll from 'mescroll.js'; 43 import 'mescroll.js/mescroll.min.css'; 44 import empty from './empty'; 45 const pagesize=10; 46 export default { 47 name: 'searchcontent', 48 props: { 49 searchname: { 50 type: string, 51 default: '' 52 }, 53 successinvite: { 54 type: array, 55 default: [] 56 } 57 }, 58 data() { 59 return { 60 datalist: [], 61 mescroll: null, //mescroll实例对象 62 totalpage:1, 63 isempty:false 64 } 65 }, 66 components:{ 67 empty 68 }, 69 watch: { 70 'searchname' () { 71 this.datalist = [];//要清空,不然有时候会出现上拉加载不了 72 this.searchname !== '' && this.mescroll.resetupscroll(); 73 } 74 }, 75 mounted () { 76 console.log(this.searchname) 77 this.mescroll = new mescroll(this.$refs.mescroll, { //在mounted初始化mescroll,确保此处配置的ref有值 78 down:{islock: true}, //下拉刷新的配置. (如果下拉刷新和上拉加载处理的逻辑是一样的,则down可不用写了) 79 up: { 80 callback: this.upcallback, 81 // 以下是一些常用的配置,当然不写也可以的. 82 page: { 83 num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始 84 size: 10, //每页数据条数,默认10 85 }, 86 htmlloading: '<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">正在加载中..</p>', 87 htmlnodata: '<p class="upwarp-nodata" style="height:.4rem">当当当~已经到底啦~</p>', 88 nomoresize: 1, //如果列表已无数据,可设置列表的总数量要大于5才显示无更多数据; 89 isbounce: true, 90 }, 91 down:{ 92 use:false 93 }, 94 }); 95 }, 96 methods: { 97 //点击调起个人主页 98 openuserclick (item) { 99 console.log(item) 100 var userid = item; 101 mui.openclient({"pagetype": "userhome","userid":item}); 102 }, 103 //上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10 104 upcallback(page) { 105 //联网请求 106 this.$request.post(_basepath + '/activity/page20191018/searchall.html', {hintkey:this.searchname,searchtype:91,pageno:page.num,pagesize:page.size,actionsource:'07'}).then((response) => { 107 if(response && response.resultlist){ 108 // 请求的列表数据 109 let result = response.resultlist[0]; 110 let arr = result.list; 111 // 如果是第一页需手动置空列表 112 if (page.num === 1) this.datalist = [] 113 // 把请求到的数据添加到列表 114 this.datalist = this.datalist.concat(arr) 115 // 数据渲染成功后,隐藏下拉刷新的状态 116 this.totalpage = result.total % pagesize > 0 ? math.floor(result.total / 10 + 1) : result.total / 10;//计算总页数超过就不loadmore 117 this.$nexttick(() => { 118 this.mescroll.endsuccess(arr.length); 119 this.mescroll.endbypage(arr.length, this.totalpage) 120 }) 121 }else{ 122 this.isempty = true; 123 this.mescroll.enderr(); 124 } 125 }).catch(() => { 126 this.mescroll.enderr(); 127 }) 128 }, 129 inviteclick(item) { 130 this.$emit('inviteclick',item); 131 } 132 } 133 134 } 135 </script> 136 137 <style lang="scss" scoped> 138 .mescroll { 139 position: fixed; 140 top: .9rem; 141 bottom: 0; 142 left:0; 143 height: auto; 144 } 145 .search-content{ 146 padding:0 .24rem; 147 background: #121223; 148 ul{ 149 height:auto; 150 .item{ 151 display:flex; 152 justify-content:space-between; 153 align-items:center; 154 width:100%; 155 height:1.56rem; 156 .personblock{ 157 display:flex; 158 justify-content: flex-start; 159 align-items: center; 160 .showimg{ 161 position:relative; 162 width:1rem; 163 height:1rem; 164 margin-right:.16rem; 165 border:.02rem solid #51516d; 166 border-radius:50%; 167 box-sizing: border-box; 168 img{width:100%;height:100%;border-radius:50%} 169 .icon{ 170 position: absolute; 171 bottom:0; 172 right:0; 173 width:.28rem; 174 height:.28rem; 175 background-image:url(); 176 background-repeat:no-repeat; 177 background-size:contain; 178 &.c_company{background-image:url(../../images/c_company.png);} 179 &.c_person{background-image:url(../../images/c_person.png);} 180 &.c_kol{background-image:url(../../images/kol.png);} 181 } 182 } 183 .showinfo{ 184 .name{font-size:.3rem;color:#fff;font-weight:500;line-height:.42rem;text-align:left;} 185 .attentioncount{font-size:.26rem;font-weight:400;color:#716d80;text-align:left;} 186 } 187 } 188 189 .sendbtn{ 190 width:1.44rem; 191 height:.56rem; 192 line-height:.56rem; 193 background:#ff005e; 194 border-radius:.28rem; 195 color:#fff; 196 text-align:center; 197 &.active{background:#2c2b41;color:#fff} 198 } 199 } 200 } 201 } 202 203 </style>
填坑处理:
1、用户未输入搜索关键词时,mescroll不能就直接初始话,要在用户输入的时候才能初始化,所以子组件就接受了父组件的keyword,并用
watch: {
'searchname' () {
this.datalist = [];//要清空,不然有时候会出现上拉加载不了
this.searchname !== '' && this.mescroll.resetupscroll();
}
},
2、搜索完以后点击搜索输入框右边里的关闭按钮,发现其他列表不能滑动。解决方法:要加:isbounce: true,
如对本文有疑问, 点击进行留言回复!!
vue源码实战render.js与$nextTick的异步调用
同事牛逼啊,写了个隐藏 bug,我排查了 3 天才解决问题!
【JavaScript笔记(一)】万丈高楼平地起 - 基本概念篇
网友评论