星期四一朋友(没错就是上周分享遇到问题那朋友)发了他应用发给使用,让看看有没有什么优化的问题(也是可怜他们公司就他一个前端)!大概看了下,基本上每个模块都是列表→详情页这样的模式!可能刚好公司的无线网有点卡吧,基本上列表页跳详情页都是卡得不要不要的,更是出现空白页的现象,正好也没事儿,让他把代码发来看看,不看不知道一看吓一跳!他的列表到详细页面每点击一次都会打开一个新的webview,返回的时候也没有重写mui.back。后面给他讲了下需要优化的地方,也不知道他有没有改完。这里就写下我觉得怎么优化的方法吧!
相关文档:
自定义事件:http://dev.dcloud.net.cn/mui/event/#customevent
-------------------------------------------------------------------------------------------------------------------------------------------
预加载详情页
在列表页中预加载详情页,列表页中点击某新闻时,通过自定义事件通知详情页加载对应新闻详情,这样可以避免每次打开新闻详情时重新创建webview的资源消耗。
mui.plusReady(function() {
//预加载详情页
webview_detail = mui.preload({
url: 'dataShow.html',
id: 'dataShow',
styles: {
"render": "always",//一直渲染
"popGesture": "hide",
"titleNView": titleNView
}
});
});
详情页的内容需要通过ajax从服务端动态获取,获取之后再渲染。实际上详情页部分内容在列表页已经加载过(标题之类的)可以直接从列表页传递过来,而无需等待网络响应。因此,在列表页点击事件中,将列表页已加载的、详情页也需要的信息通过自定义事件传递给详情页,详情页将这些数据立即渲染,然后再通过ajax动态获取其余部分的数据。这样就不会出现白屏或者很明显的卡顿了。
1、列表页点击事件中传递已加载数据
//触发子窗口变更新闻详情
mui.fire(webview_detail, 'get_data', {
guid: guid,//唯一标示
title:title,//标题
author:author,//作者
time:time,//事件
content:content//内容(有很多列表上有简介,其实就是内容的截取)
});
2、详情页获取前页数据后,立即渲染,再通过ajx请求其余数据(就按照他那列表显示的东西,这里ajax都可以不用请求了,基本直接从列表页传就行)
//监听自定义事件,获取详情
document.addEventListener('get_data', function(event) {
var guid = event.detail.guid;
if(!guid) {
return;
}
//前页传入的数据,直接渲染,无需等待ajax请求详情后
document.getElementById("title").value=event.detail.title;
document.getElementById("author").value=event.detail.author;
document.getElementById("content").value=event.detail.content;
//向服务端请求文章其他信息
mui.ajax('your-server-url' + guid, {
type:'GET',
dataType: 'json', //服务器返回json格式数据
timeout: 15000, //15秒超时
success: function(data) {
//这里再对其他进行渲染
},
error: function(xhr, type, errorThrown) {
mui.toast('获取文章内容失败');
//TODO 此处可以向服务端告警
}
});
});
3、重写返回(mui.back)清除页面数据
为了避免打开下一个新闻详情时,闪一下上一个新闻详情,模板在详情页返回时,需要清空详情页数据
//重写返回逻辑,返回时隐藏详情页webview
mui.back = function() {
//这里写清除数据的方法
plus.webview.currentWebview().hide("auto", 300);//隐藏当前页
}
这种就是基于mui预加载来优化列表页跳转详情页的方法
不过估计上面那种优化方法对他来说对代码的改动量相当大,所以想到一个折中的方法。
应急方法(不推荐使用)
先说说思路,mui.openWindow方法打开新页面的时候其实我们是能获取到页面的id的,我们在每次点击详情打开详情页面的时候我第一次打开的时候创建页面,后期打开的时候我只是去刷新页面(和上面方法类似),这样能就不会去平凡的创建页面。
1、首先我们对mui.openWindow方法进行简单的封装
/**
* 显示窗体
* @param {Object} id
* @param {Object} url
*/
function toShowWindow(id,url,onComplete){
if(id == null || id == "")
id = url ;
var webview = plus.webview.getWebviewById(id);
if(webview != null){//判断该页面是不是第一次打开
webview.show() ;//如果该页面存在就直接显示
//发送页面显示事件
mui.fire(webview,"get_data",{}) ;//触发自定义事件
if(onComplete != null)
onComplete(webview) ;
}else{
if(id == null || id == "")
id = url ;
var webview = mui.openWindow({
url: url,
id: id,
createNew:true,
styles:{
scalable:true
},
waiting:{
title:"数据加载中..."
},
show: {
aniShow: 'slide-in-right',
duration: 100
}
});
if(onComplete != null){
if(plus.os.name == "Android"){
onComplete(webview) ;
}else{
window.setTimeout(function(){
onComplete(webview) ;
},200) ;
}
}
}
return webview ;
}
2、列表页打开详情页面
//tap事件 mui里面的点击事件
mui(".mui-table-view").on("tap", "li", function() {
var guid= this.getAttribute("guid");
if(guid== null || guid== "")
return;
var winId = "dataShow"
//打开dataShow.html 页面,并触发dataShow()方法
toShowWindow(winId, "dataShow.html", function(win) {
win.evalJS("dataShow('" + guid+ "')");
});
});
3、详情页面方法
function dataShow(guid) {
mui.ajax('your-server-url' + guid, {
type:'GET',
dataType: 'json', //服务器返回json格式数据
timeout: 15000, //15秒超时
success: function(data) {
//赋值
setData2Tag(data)
},
error: function(xhr, type, errorThrown) {
mui.toast('获取文章内容失败');
//TODO 此处可以向服务端告警
}
});
}
/**
* 将对象中的值绑定到页面标签中 这个要在标签设置setData="true"
* @param {Object} data
*/
function setData2Tag(data,filter){
if(data == null)
return ;
if(filter == null)
filter = "";
$("*[setData=true]"+filter).each(function(i){
var nameKey = null ;
var tagName = this.tagName ;
var flag = 0 ;
if(tagName == "DIV" || tagName == "SPAN"){
flag = 1 ;
nameKey = this.id ;
}else if(tagName == "BUTTON"){
flag = 2 ;
nameKey = this.name ;
}else{
nameKey = this.name ;
}
if(nameKey == null ||nameKey == "")
return ;
var value = data[nameKey] ;
if(value != null && value!=""){
if(flag == 1)
$(this).html(value) ;
else if(flag == 2)
$(this).innerText=value ;
else
$(this).val(value) ;
}
}) ;
}
这样每次去点击的时候会通过ID去判断页面是否存在,不存在创建,存在就显示,通过id发送ajax请求去渲染数据
如果是新应用建议一开始就是用第一种方法(如果你想偷懒用第二种也没毛病),但是你的应用已经成型,需要修改的地方太多,就用第二种应急的方法吧!明天早上去问下他搞定没,没弄好就推荐他第二种应急的方法吧!