我的需求是:在列表页,可以按照时间进行搜索,并且需要实现下拉刷新,上拉加载的效果。
我是用双webview写的。父页面是搜索条件,子页面是列表。
第一个问题,在父页面不显示日期选择器,因为子页面的层级比父页面高,子页面遮盖了弹出的选择器。搜索了一下,没有发现简单好用的解决方法,综合几个答案,最终决定在子页面写选择器,在父页面触发子页面的自定义事件,弹出选择器。(一步一步贴代码)
父页面(dealer-main.html),点击input时的事件:
var list = plus.webview.getWebviewById("dealer.html");
mui.fire(list,"showPicker",{})
list.show();
子页面(dealer.html)
window.addEventListener("showPicker",function(event){
var params = { "type": "date"};
var dtPicker = new mui.DtPicker(params);
dtPicker.show(function (res) {
// 选择日期之后,将值返回到父页面,触发父页面的自定义事件 backPicker
var list = plus.webview.getWebviewById("dealer-main.html");
mui.fire(list,"backPicker",{
type:event.detail.type,
value:res.text
})
list.show();
})
})
父页面自定义事件(backPicker)
window.addEventListener("backPicker",function(event){
//赋值
vm.$data.StartTime = event.detail.value;
})
这样写出现的第一个问题是父页面的选择器可以多次点击,每次都会触发子页面的showPicker事件,导致弹出一堆选择器框,自然是不行的。
我想到的解决方法是,在父页面定义一个变量n,值为数值0,每次点击input,这个数字都加1,并且作为参数传给子页面。在子页面判断如果n>=2,return,不弹出选择器,因为n大于等于2的情况就是多次点击父页面的input了,并且在父页面的backPicker事件里面重新给n赋值为0。暂且解决这个问题,但是会出现新问题,点击选择器的取消按钮,或者安卓(我暂时只用了安卓)的物理返回键,或者选择器的mask的时候,选择器隐藏掉,但是再次点击父页面的input,无法触发子页面的showPicker事件,很简单,n>=2了。然而,比较令我开心的是,我发现不管是点击选择器的取消,还是安卓的物理返回键,还是选择器的mask,其根本都是触发mui.picker.js的hide事件,那我觉得此时只能重写hide方法了。然而,在重写hide方法之前先说另外一个问题。
在子页面调出选择器的时候,年月日这些选项只能上划选择,不能下滑选择,原因也很简单,因为子页面有下拉刷新,下滑选择时间的时候,整个子页面都会下拉,这个问题我搜索了一下,真有解决方法,并且很好用。就是禁止页面刷新,结束后再重新释放。代码如下:
mui('#vmMain').pullRefresh().setStopped(true);//暂时禁止滚动
mui('#vmMain').pullRefresh().setStopped(false);//开启禁止滚动
下面说重写mui的选择器的picker的hide方法。
这是mui.picker.js的源码
hide: function() {
var i = this;
if(!i.disposed) {
var n = i.ui;
n.picker.classList.remove(e.className("active")), n.mask.close(),t.body.classList.remove(e.className("dtpicker-active-for-page")), e.back = i.__back
}
},
需要重写的就是这部分代码,重写后的代码如下:
var params = { "type": "date"};
var dtPicker = new mui.DtPicker(params);
//定义一个Boolean,控制选择器的弹出
var boo = true;
//重写日期选择器的hide方法
dtPicker.hide = function(){
boo = true;
//隐藏选择器的时候把禁止滚动去掉
mui('#vmMain').pullRefresh().setStopped(false);//开启禁止滚动
var i = this;
if(!i.disposed){
var n=i.ui;
n.picker.classList.remove(mui.className("active")),
n.mask.close(),
document.body.classList.remove(mui.className("dtpicker-active-for-page")),
mui.back=i.__back
}
}
下面贴稍微完整一些的代码,我会在注释里写清楚我每一步的思路:
父页面
//触发input的方法
blur(type){
//定义的n初始值为0,每次点击input都+1;
this.n++;
var list = plus.webview.getWebviewById("dealer.html");
//触发子页面的自定义事件 showPicker,
mui.fire(list,"showPicker",{
n:this.n//将n作为参数传过去,判断是否是第一次点击input
})
list.show();
},
//在子页面触发此事件 backPicker
window.addEventListener("backPicker",function(event){
//每次返回首先将n重新赋值为0
vm.$data.n = 0;
//将子页面返回的时间值赋值给input框
vm.$data.StartTime = event.detail.value;
})
子页面
//我只需要年月日,并不需要时分秒,故在此定义
var params = { "type": "date"};
//初始化时间选择器
var dtPicker = new mui.DtPicker(params);
//定义boolean,用于判断选择器可以弹出的时间
var boo = true;
//重写日期选择器的hide方法
dtPicker.hide = function(){
//将boo赋值为true,此步不用写,因为boo为true并未在其他地方改变过
boo = true;
//在选择器开启的时候会禁止页面滚动,隐藏的时候解开
mui('#vmMain').pullRefresh().setStopped(false);//开启禁止滚动
//下面这部分就是mui.picker.js的hide方法的源码了,我并没有深入分析,在此不再详解
var i = this;
if(!i.disposed){
var n=i.ui;
n.picker.classList.remove(mui.className("active")),
n.mask.close(),
document.body.classList.remove(mui.className("dtpicker-active-for-page")),
mui.back=i.__back
}
}
//自定义事件showPicker
window.addEventListener("showPicker",function(event){
//禁止重复打开选择器
if(event.detail.n >= 2 && !boo)return;
//当显示选择器之前 先将子页面禁止滚动
mui('#vmMain').pullRefresh().setStopped(true);//暂时禁止滚动
//当显示选择器
dtPicker.show(function (res) {
//点击选择器的确定按钮,首先页面设置为可以滚动 然后出发父页面的自定义事件backPicker, 将日期传过去
mui('#vmMain').pullRefresh().setStopped(false);//开启禁止滚动
var list = plus.webview.getWebviewById("dealer-main.html");
mui.fire(list,"backPicker",{
value:res.text
})
list.show();
})
})
到此就结束了,可能有更简单且高效的方法吧,但我目前没查到,毕竟是渣渣,API都不熟悉
暂时还没测出问题,有问题再更新啦。
其实我还有个小需求,就是将选择器的取消按钮换成清空按钮,还在研究中......
网友评论