hbuilder 开发APP填坑经验

时间:2022-05-06
本文章向大家介绍hbuilder 开发APP填坑经验,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

hbuilder中进行窗口管理有2种方式,一种是用了mui框架,可以用mui提供的管理方式,都封装好了。

还有一种是没有用mui,可以直接通过最底层的plus.webview来管理窗口的操作。

官方文档地址:http://www.dcloud.io/docs/api/zh_cn/webview.html

我们创建一个H5+的项目,在common.js中默认有对窗口管理的代码,可以直接使用。

在使用的过程中我遇到了下面的问题:

1,在APP下面有一个toolbar,目前每次点击一个按钮都是通过webview创建一个新的view,view中去加载网页(我们的功能实现都是通过h5的方式嵌入到app中)

common.js提供的方法源码如下:

/**
 * 打开新窗口
 * @param {URIString} id : 要打开页面url
 * @param {boolean} wa : 是否显示等待框
 * @param {boolean} ns : 是否不自动显示
 * @param {JSON} ws : Webview窗口属性
 */
w.clicked=function(id,wa,ns,ws){
    if(openw){//避免多次打开同一个页面
        return null;
    }
    if(w.plus){
        wa&&(waiting=plus.nativeUI.showWaiting());
        ws=ws||{};
        ws.scrollIndicator||(ws.scrollIndicator='none');
        ws.scalable||(ws.scalable=false);
        var pre='';//'http://192.168.1.178:8080/h5/';
        openw=plus.webview.create(pre+id,id,ws);
        ns||openw.addEventListener('loaded',function(){//页面加载完成后才显示
//        setTimeout(function(){//延后显示可避免低端机上动画时白屏
            openw.show(as);
            closeWaiting();
//        },200);
        },false);
        openw.addEventListener('close',function(){//页面关闭后可再次打开
            openw=null;
        },false);
        return openw;
    }else{
        w.open(id);
    }
    return null;
};

我们直接调用clicked('http://cxytiandi.com',true)就可以打开猿天地的首页,APP中toolbar对应的几个模块的主页肯定会来回切换的,导致每次切换都需要重新渲染,我通过改造clicked方法来实现下面的需求:

  • 如果页面对应的view没创建,就创建新的
  • 如果页面对应的view已经存在,就直接打开已经存在的

直接上改造后的代码:

wa&&(waiting=plus.nativeUI.showWaiting());
        ws=ws||{};
        ws.scrollIndicator||(ws.scrollIndicator='none');
        ws.scalable||(ws.scalable=false);
        var pre='';//'http://192.168.1.178:8080/h5/';
        if(ws.createNew==false){
            openw = plus.webview.getWebviewById( id );
            if (openw == null) {
                openw=plus.webview.create(pre+id,id,ws);
            } else {
                openw.show(as);
                closeWaiting();
                return openw;
            }
        } else {
            openw=plus.webview.create(pre+id,id,ws);
        }

通过在ws对象中加一个createNew参数来决定是否要创建新的view,如果配置为false的话,就通过plus.webview.getWebviewById去查找之前有没有创建过,有就直接显示,不用创建了,使用代码如下:

clicked('http://cxytiandi.com',true, false,{createNew:false});

2,通过webview打开的页面,可以通过back()来返回到上个页面,源码如下:

// 处理返回事件
w.back=function(hide){
    if(w.plus){
        ws||(ws=plus.webview.currentWebview());
        if(hide||ws.preate){
            ws.hide('auto');
        }else{
            ws.close('auto');
        }
    }else if(history.length>1){
        history.back();
    }else{
        w.close();
    }
};

有些场景,比如在我的主页点击关注的用户,进入用户主页,在用户主页取消关注,然后回退到我的主页中,回退相当于重新打开之前开启过的view,这个时候我的页面中的关注数还是之前的,取消关注的并没有从总关注数中减去,今天我在回退的基础上做了扩展, 可以支持回退的时候指定是否要刷新上个页面,可以解决这个问题。

但是刷新页面其实用户体验很差的,最好的办法是异步加载,只改变需要改变的地方,为了支持这个我还加了一个回调的方法,可以支持方法回调,你可以自己写逻辑去实现数据刷新。

主要还是改造clicked方法,因为view是在clicked中创建的,在回退的时候我们可以通过监听view的close方法来实现这个操作

openw.addEventListener('close',function(){//页面关闭后可再次打开
            //可以设置页面关闭时回调的方法,可以对数据进行重新加载操作
            if(callback){
                callback(callbackParams);
            }
            //页面关闭时需要刷新上个页面
            if (ws.closeRefresh==true){
                window.location.reload();
            }
            openw=null;
        },false);

完整的clicked方法如下:

/**
 * 打开新窗口
 * @param {URIString} id : 要打开页面url
 * @param {boolean} wa : 是否显示等待框
 * @param {boolean} ns : 是否不自动显示
 * @param {JSON} ws : Webview窗口属性
 * @param {function} callback : 页面回退关闭时执行的回调方法
 * @param {JSON} callbackParams : 回调方法的参数
 */
w.clicked=function(id,wa,ns,ws,callback,callbackParams){
    /*if(openw){//避免多次打开同一个页面
        return null;
    }*/
    if(w.plus){
        wa&&(waiting=plus.nativeUI.showWaiting());
        ws=ws||{};
        ws.scrollIndicator||(ws.scrollIndicator='none');
        ws.scalable||(ws.scalable=false);
        var pre='';//'http://192.168.1.178:8080/h5/';
        if(ws.createNew==false){
            openw = plus.webview.getWebviewById( id );
            if (openw == null) {
                openw=plus.webview.create(pre+id,id,ws);
            } else {
                openw.show(as);
                closeWaiting();
                return openw;
            }
        } else {
            openw=plus.webview.create(pre+id,id,ws);
        }
        ns||openw.addEventListener('loaded',function(){//页面加载完成后才显示
//        setTimeout(function(){//延后显示可避免低端机上动画时白屏
            openw.show(as);
            closeWaiting();
//        },200);
        },false);
        openw.addEventListener('close',function(){//页面关闭后可再次打开
            //可以设置页面关闭时回调的方法,可以对数据进行重新加载操作
            if(callback){
                callback(callbackParams);
            }
            //页面关闭时需要刷新上个页面
            if (ws.closeRefresh==true){
                window.location.reload();
            }
            openw=null;
        },false);
        return openw;
    }else{
        w.open(id);
    }
    return null;
};

回退关闭时刷新使用代码如下:

clicked('http://cxytiandi.com',true, false,{closeRefresh:true});

回退关闭时执行回调代码使用代码如下:

clicked('http://cxytiandi.com',true, false,{},ref,{id:1001});
function ref(data) {
   console.log(data.id);
}

3, 安卓手机上都有一个回退的按钮,相当于苹果中从左往右滑动,到了主页的时候如果点击了2次回退的按钮,需要提示是否退出app,这个可以通过监听来实现:

function plusReady(){
    ws=plus.webview.currentWebview();
    // Android处理返回键
    plus.key.addEventListener('backbutton',function(){
        var hurl = window.location.href;
        if(hurl.indexOf("/house/index") > 0 || hurl.indexOf("/quotations/index") > 0
                || hurl.indexOf("/loanInfo/list") > 0 || hurl.indexOf("/selfInfo/index") > 0) {
            plus.nativeUI.confirm("确认退出",function(e) {
                if(e.index == 0) {
                    plus.runtime.quit(); 
                }
            });
        } else {
            back();
        }
    },false);
    compatibleAdjust();
}