HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于安卓高德地图的手机黑屏花屏模糊等症状处理

安卓高德用户在打开加载地图的webview时候,打开方式为:

var newCarrental = plus.webview.getWebviewById("加载webview页面");  
newCarrental.setStyle({  
height: '100%',  
width: '100%',  
right: '0px',  
background: "transparent",  
render: 'always'//此属性务必要加载  
});  
if(newCarrental == null) {  
    plus.webview.create("加载webview页面", "加载webview页面别名", subpage_style).show("slide-in-right");  
} else {  
    newCarrental.show("slide-in-right");  
}

然后这样打开的弊端为:打开页面会很暂用手机内存,当用户在这个页面打开的基础上,如果还要大概一个新的地图页面,那么新的地图会被前面的地图遮挡,有一个解决方案为:用户打开新地图页面的时候吧之前打开的页面top值修改或者关掉之前的页面,离开或者返回的时候要把top值修改掉,如果是在基础之上在打开新的地图页面的话不建议关闭之前的地图页面,具体代码如下:

//用户打开新地图页面执行代码  
var sub = plus.webview.getWebviewById("之前地图页面名称");  
if(sub != null) {  
    sub.setStyle({  
        top: '100%'  
    });  
}  
//用户关闭新地图页面执行代码  
var sub = plus.webview.getWebviewById("之前地图页面名称");  
if(sub != null) {  
    sub.setStyle({  
        top: '0'  
    });  
}

如果有问题可以留言,相互学习

继续阅读 »

安卓高德用户在打开加载地图的webview时候,打开方式为:

var newCarrental = plus.webview.getWebviewById("加载webview页面");  
newCarrental.setStyle({  
height: '100%',  
width: '100%',  
right: '0px',  
background: "transparent",  
render: 'always'//此属性务必要加载  
});  
if(newCarrental == null) {  
    plus.webview.create("加载webview页面", "加载webview页面别名", subpage_style).show("slide-in-right");  
} else {  
    newCarrental.show("slide-in-right");  
}

然后这样打开的弊端为:打开页面会很暂用手机内存,当用户在这个页面打开的基础上,如果还要大概一个新的地图页面,那么新的地图会被前面的地图遮挡,有一个解决方案为:用户打开新地图页面的时候吧之前打开的页面top值修改或者关掉之前的页面,离开或者返回的时候要把top值修改掉,如果是在基础之上在打开新的地图页面的话不建议关闭之前的地图页面,具体代码如下:

//用户打开新地图页面执行代码  
var sub = plus.webview.getWebviewById("之前地图页面名称");  
if(sub != null) {  
    sub.setStyle({  
        top: '100%'  
    });  
}  
//用户关闭新地图页面执行代码  
var sub = plus.webview.getWebviewById("之前地图页面名称");  
if(sub != null) {  
    sub.setStyle({  
        top: '0'  
    });  
}

如果有问题可以留言,相互学习

收起阅读 »

解决MUI选择器组件抛出“picker.getSelectedItem is not a function”异常的问题

bug反馈 picker 选择器

【背景介绍】
  MUI 版本 3.3。
  在页面中使用了 Pop-Picker 组件(mui-picker)。

【问题阐述】
  当点击选择器的“确定”按钮时,页面上抛出如下异常:

Uncaught TypeError: picker.getSelectedItem is not a function at src bs/mui/mui.poppicker.js:117

【解决方案】
  几经排查,发现当页面内引入的 js 中包含了对 Array 原型链方法扩充时,会抛出这个异常。
  定位到 mui.poppicker.js 第 112 行 getSelectedItems() 方法中,原先的:

for (var i in self.pickers) {  
    var picker = self.pickers[i];  
    items.push(picker.getSelectedItem() || {});  
}

  修改为:

for (var i = 0, len = self.pickers.length; i < len; i++) {  
    var picker = self.pickers[i];  
    items.push(picker.getSelectedItem() || {});  
}

  问题解决。

【后记】
  查找资料时发现 http://ask.dcloud.net.cn/question/14800 这样一个问题,题主应该是遇到了和我同样的错误。
  现在大多数开发者手头都会有几个工具库来扩充原型链方法, String.prototype.trim = function(); 这种经典的方法就不提了,为了应对低版本浏览器,对 Array.prototype.forEach = function(); 这类 ES5 常用方法也有必要做 polyfil,我本人遇到这个问题是因为扩充了 Array.prototype.remove = function();
  Javascript 里 for in 遍历因为原型链的缘故本来就有潜在的坑,不如老老实实写 for 循环,必要时还需要使用 hasOwnProperty() 辅助判断,也希望大家引以为戒吧。

继续阅读 »

【背景介绍】
  MUI 版本 3.3。
  在页面中使用了 Pop-Picker 组件(mui-picker)。

【问题阐述】
  当点击选择器的“确定”按钮时,页面上抛出如下异常:

Uncaught TypeError: picker.getSelectedItem is not a function at src bs/mui/mui.poppicker.js:117

【解决方案】
  几经排查,发现当页面内引入的 js 中包含了对 Array 原型链方法扩充时,会抛出这个异常。
  定位到 mui.poppicker.js 第 112 行 getSelectedItems() 方法中,原先的:

for (var i in self.pickers) {  
    var picker = self.pickers[i];  
    items.push(picker.getSelectedItem() || {});  
}

  修改为:

for (var i = 0, len = self.pickers.length; i < len; i++) {  
    var picker = self.pickers[i];  
    items.push(picker.getSelectedItem() || {});  
}

  问题解决。

【后记】
  查找资料时发现 http://ask.dcloud.net.cn/question/14800 这样一个问题,题主应该是遇到了和我同样的错误。
  现在大多数开发者手头都会有几个工具库来扩充原型链方法, String.prototype.trim = function(); 这种经典的方法就不提了,为了应对低版本浏览器,对 Array.prototype.forEach = function(); 这类 ES5 常用方法也有必要做 polyfil,我本人遇到这个问题是因为扩充了 Array.prototype.remove = function();
  Javascript 里 for in 遍历因为原型链的缘故本来就有潜在的坑,不如老老实实写 for 循环,必要时还需要使用 hasOwnProperty() 辅助判断,也希望大家引以为戒吧。

收起阅读 »

chrome调试android虚拟机简单易操作版(基于官方)

Android chrome 调试 学习

首先我们要用chrome调试我们的APP,就先得有chrome浏览器和hbuilder编辑器,hbuilder编辑器大家应该都有,chrome浏览器也很好下载,这里给大家一个新版本的chrome浏览器的下载地址 http://www.chromeliulanqi.com/ ,下载完以后安装一下就行。下面开始整起来吧!
第一步,为了调试,我们在hbuilder中新建一个app,可以直接选择h5 的模板文档。如图

新建项目

第二步,连接上你的模拟器或者真机,
1.如果想使用模拟器的话大家可以下载一个夜神模拟器http://www.yeshen.com/,下载完夜神模拟器以后需要到hbuilder中点击顶端的选项工具,然后再点击选项进入首选页页面

修改第三方模拟器端口图1

修改第三方模拟器端口图2

2.如果你想要使用真机测试的话,打开真机的开发者选项,具体的可以在电脑上下载一个360手机助手,根据360手机助手的提示操作,如果还是连接不上你的手机,可以在你的android手机上安装一个360连接助手,也是360的产品(我并不是360的宣传大使啊。。。),这样就可以完美解决hbuilder连接不上真机的情况了。
第三步,在你模拟器或者真机上运行在hbuilder上app项目,下面是2种运行app的方式。点开你想要检查的页面。如果是真机的话,会在手机上提示你是否要安装,当然要点击安装按钮。

安装应用方法1

安装应用方法2

第四步,打开chrome浏览器,在地址栏输入“chrome://inspect”,这时浏览器会出现下面这个界面。点击右边的红色箭头所指的是你所检查的页面地址,左边那个红色箭头所指的inspect是需要你去点击的,点击之后会弹出另外一个界面。

第五步,这时可能会出现这么一个情况,弹出的另外一个界面是白屏,这时需要翻墙一下(第一次使用的时候翻墙就行),可以下载一个GreenVPN,下载链接点此,又来广告了,http://www.greenvpn6.com/,这个软件每天有一个小时的免费使用时间,下载安装完这个vpn软件以后,连接一下vpn,接下来在你的chrome浏览器里测试一下,vpn有没有连接上,你只要输入个谷歌的地址www.google.com,如果他能进入这个地址,就说明vpn连接成功。你再点击inspect,弹出的屏幕就不会白屏了。

成功

继续阅读 »

首先我们要用chrome调试我们的APP,就先得有chrome浏览器和hbuilder编辑器,hbuilder编辑器大家应该都有,chrome浏览器也很好下载,这里给大家一个新版本的chrome浏览器的下载地址 http://www.chromeliulanqi.com/ ,下载完以后安装一下就行。下面开始整起来吧!
第一步,为了调试,我们在hbuilder中新建一个app,可以直接选择h5 的模板文档。如图

新建项目

第二步,连接上你的模拟器或者真机,
1.如果想使用模拟器的话大家可以下载一个夜神模拟器http://www.yeshen.com/,下载完夜神模拟器以后需要到hbuilder中点击顶端的选项工具,然后再点击选项进入首选页页面

修改第三方模拟器端口图1

修改第三方模拟器端口图2

2.如果你想要使用真机测试的话,打开真机的开发者选项,具体的可以在电脑上下载一个360手机助手,根据360手机助手的提示操作,如果还是连接不上你的手机,可以在你的android手机上安装一个360连接助手,也是360的产品(我并不是360的宣传大使啊。。。),这样就可以完美解决hbuilder连接不上真机的情况了。
第三步,在你模拟器或者真机上运行在hbuilder上app项目,下面是2种运行app的方式。点开你想要检查的页面。如果是真机的话,会在手机上提示你是否要安装,当然要点击安装按钮。

安装应用方法1

安装应用方法2

第四步,打开chrome浏览器,在地址栏输入“chrome://inspect”,这时浏览器会出现下面这个界面。点击右边的红色箭头所指的是你所检查的页面地址,左边那个红色箭头所指的inspect是需要你去点击的,点击之后会弹出另外一个界面。

第五步,这时可能会出现这么一个情况,弹出的另外一个界面是白屏,这时需要翻墙一下(第一次使用的时候翻墙就行),可以下载一个GreenVPN,下载链接点此,又来广告了,http://www.greenvpn6.com/,这个软件每天有一个小时的免费使用时间,下载安装完这个vpn软件以后,连接一下vpn,接下来在你的chrome浏览器里测试一下,vpn有没有连接上,你只要输入个谷歌的地址www.google.com,如果他能进入这个地址,就说明vpn连接成功。你再点击inspect,弹出的屏幕就不会白屏了。

成功

收起阅读 »

列表页面 跳转到详情页面 如何让列表页面刷新 我所用的方法

mui

比如一个待办列表 我们点击进入详情页面后进行操作 就会返回列表页面然后再次刷新列表

呃... 我琢磨了俩个方法

第一个就是

var taskList = plus.webview.getWebviewById('跳转页面ID');  
                taskList.reload();  
                mui.back();  

mui.openWindow({  
                url:'跳转页面url',  
                id:'跳转页面ID',  
                });

这个大家应该知道滴 方便又快捷 操作完后页面确实刷新了

这个方法在http://ask.dcloud.net.cn/article/617有详细介绍

然而我发现安卓4.0的版本 还是华为手机操作系统的问题 用这个方法后返回列表页面居然卡死了

于是我使用自定义事件进行跳转

详情页面

...

var taskList = plus.webview.getWebviewById('跳转页面ID');
mui.fire(跳转页面ID,'自定义事件名称');

mui.openWindow({
url:'跳转页面url',
id:'跳转页面ID',
});
...

列表页面

...
window.addEventListener('自定义事件',function(){
触发事件。。。
});
...

不过用自定义事件后 可能还有许多问题要处理 比如列表之前页面传过来的值并会变成undefined 不过相信大家应该可以轻松解决

其实我还是一只菜鸡 发文章就想赚点积分 看看文章回复下人家 不知道怎么积分就突然变负了 希望大家捧捧场 嘿嘿

继续阅读 »

比如一个待办列表 我们点击进入详情页面后进行操作 就会返回列表页面然后再次刷新列表

呃... 我琢磨了俩个方法

第一个就是

var taskList = plus.webview.getWebviewById('跳转页面ID');  
                taskList.reload();  
                mui.back();  

mui.openWindow({  
                url:'跳转页面url',  
                id:'跳转页面ID',  
                });

这个大家应该知道滴 方便又快捷 操作完后页面确实刷新了

这个方法在http://ask.dcloud.net.cn/article/617有详细介绍

然而我发现安卓4.0的版本 还是华为手机操作系统的问题 用这个方法后返回列表页面居然卡死了

于是我使用自定义事件进行跳转

详情页面

...

var taskList = plus.webview.getWebviewById('跳转页面ID');
mui.fire(跳转页面ID,'自定义事件名称');

mui.openWindow({
url:'跳转页面url',
id:'跳转页面ID',
});
...

列表页面

...
window.addEventListener('自定义事件',function(){
触发事件。。。
});
...

不过用自定义事件后 可能还有许多问题要处理 比如列表之前页面传过来的值并会变成undefined 不过相信大家应该可以轻松解决

其实我还是一只菜鸡 发文章就想赚点积分 看看文章回复下人家 不知道怎么积分就突然变负了 希望大家捧捧场 嘿嘿

收起阅读 »

页面返回后自动跳转到对应的slider,用slider.gotoPage()可以解决

tab mui

点击列表的时候把当前的tab存到sessionStorage里面,返回的时候取出来,然后判断currentTab的值

var slider = $('#slider').slider();
//
if(currentTab=='0'){

            slider.gotoPage(0,100);  

        }else if(currentTab=='1'){  

            slider.gotoPage(1,100);  

        }else if(currentTab=='2'){  

            slider.gotoPage(2,100);   

        }else if(currentTab=='3'){  

            slider.gotoPage(3,100);  
        }
继续阅读 »

点击列表的时候把当前的tab存到sessionStorage里面,返回的时候取出来,然后判断currentTab的值

var slider = $('#slider').slider();
//
if(currentTab=='0'){

            slider.gotoPage(0,100);  

        }else if(currentTab=='1'){  

            slider.gotoPage(1,100);  

        }else if(currentTab=='2'){  

            slider.gotoPage(2,100);   

        }else if(currentTab=='3'){  

            slider.gotoPage(3,100);  
        }
收起阅读 »

上传多张照片到服务器

        var server = **********; //上传文件的端口  
        var files = []; //文件的数组  
        document.getElementById("ContractID-btn").addEventListener('tap', function() {  
            plus.gallery.pick(function(e) {  
                document.getElementById("ContractID-btn").innerText = '选择照片(' + e.files.length + ')张';  
                //从相册添加文件  
                appendFile(e); //添加文件  
            }, function(e) {  
                // outSet("取消选择图片");  
            }, {  
                filter: "image",  
                multiple: true,  
                system: false  
            });  
        });  
        //上传文件  
        function uploadContract() {  
            var task = plus.uploader.createUpload(server, {  
                method: "POST"  
            }, function(t, status) {  
                if(status == 200) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast('上传成功');  
                    ContractZIP = JSON.parse(t.responseText).fileName;  
                    rowContract = JSON.parse(t.responseText).rawFiles;  
                } else {  
                    alert('上传失败,请重试');  
                }  
            });  
            task.addData("fileType", "合同");  
            task.addData("customerId", CustomerId);  
            for(var i = 0; i < files.length; i++) {  
                var f = files[i];  
                task.addFile(f.path, {  
                    key: f.name  
                });  
            }  
            task.start();  
        }  
        //添加文件            
        function appendFile(p) {  
            plus.nativeUI.showWaiting("正在上传...");  
            var index = 1;  
            files = []; //清空数组,防止重复上传  
            for(var i = 0; i < p.files.length; i++) {  
                var n = p.files[i].substr(p.files[i].lastIndexOf('/') + 1);  
                files.push({  
                    name: "uploadkey" + index,  
                    path: p.files[i]  
                });  
                index++;  
            }  
            uploadContract();//添加完文件,开始上传  
        }
继续阅读 »
        var server = **********; //上传文件的端口  
        var files = []; //文件的数组  
        document.getElementById("ContractID-btn").addEventListener('tap', function() {  
            plus.gallery.pick(function(e) {  
                document.getElementById("ContractID-btn").innerText = '选择照片(' + e.files.length + ')张';  
                //从相册添加文件  
                appendFile(e); //添加文件  
            }, function(e) {  
                // outSet("取消选择图片");  
            }, {  
                filter: "image",  
                multiple: true,  
                system: false  
            });  
        });  
        //上传文件  
        function uploadContract() {  
            var task = plus.uploader.createUpload(server, {  
                method: "POST"  
            }, function(t, status) {  
                if(status == 200) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast('上传成功');  
                    ContractZIP = JSON.parse(t.responseText).fileName;  
                    rowContract = JSON.parse(t.responseText).rawFiles;  
                } else {  
                    alert('上传失败,请重试');  
                }  
            });  
            task.addData("fileType", "合同");  
            task.addData("customerId", CustomerId);  
            for(var i = 0; i < files.length; i++) {  
                var f = files[i];  
                task.addFile(f.path, {  
                    key: f.name  
                });  
            }  
            task.start();  
        }  
        //添加文件            
        function appendFile(p) {  
            plus.nativeUI.showWaiting("正在上传...");  
            var index = 1;  
            files = []; //清空数组,防止重复上传  
            for(var i = 0; i < p.files.length; i++) {  
                var n = p.files[i].substr(p.files[i].lastIndexOf('/') + 1);  
                files.push({  
                    name: "uploadkey" + index,  
                    path: p.files[i]  
                });  
                index++;  
            }  
            uploadContract();//添加完文件,开始上传  
        }
收起阅读 »

设置数字键盘的方法

<input type="number" pattern="\d*"/>

<input type="number" pattern="\d*"/>

我觉得这个启动时间优化空间很大!

性能优化

我觉得这个启动时间优化空间很大!

比我的Dreamweaver cs5 打开都慢很多!

我觉得这个启动时间优化空间很大!

比我的Dreamweaver cs5 打开都慢很多!

【示例】 Mui v3.3.0使用dialog实现密码的输入及验证

弹出框 技术分享 mui

需求描述

使用dialog弹出密码输入框,用户输入密码并且密码验证通过后方可关闭dialog。

需求分析

首先,dialog中提供密码输入框。
其次,用户输入密码后对密码进行验证。
最后,通过验证则关闭dialog,否则不关闭dialog并提示错误信息。

实现思路

dialog

mui提供了许多dialog,只有mui.prompt()提供了输入框,但它并不是密码框。
mui.confirm()的message参数,可以传html代码段来展示密码框,就选它了。

回调函数

由于当前版本mui,点击dialog中的按钮均会关闭dialog,所以需要对dialog按钮的默认行为进行修改。
注:下个版本会更新此修改,目前需要的话请下载附件中的mui.js文件。

验证密码

对用户输入的密码进行验证后,如果验证失败,则需要做出相应的提示。
和密码框的思路一样,使用一个文本内容默认为空的元素来展示错误信息。

功能实现

密码输入框

使用mui.confirm()弹出密码输入框。

mui.confirm('<input type="password" id="test" />', 'Hello MUI', null, function(e) {},'div');  

注:这里需要声明使用H5模式的dialog,参考文档dialog

阻止关闭dialog

用户输入完成后,点击”确认“按钮,验证密码。

mui.confirm('<input type="password" id="test" />', 'Hello MUI', null, function(event) {  
    var index = event.index;  
    if(index === 1) {  
        var pwd = document.getElementById('test').value;  
        // 验证失败返回false  
        return false;  
    }  
},'div');  

修改按钮的默认行为后,在回调函数中返回false,则不会关闭dialog。

错误信息

在拼接密码输入框的同时,见错误信息提示的元素一起拼接。

mui.confirm('<input type="password" id="test" /><span id="error">&nbsp</span>', 'Hello MUI', null, function(event) {},'div');  

源码

附上源码,直接浏览即可。

继续阅读 »

需求描述

使用dialog弹出密码输入框,用户输入密码并且密码验证通过后方可关闭dialog。

需求分析

首先,dialog中提供密码输入框。
其次,用户输入密码后对密码进行验证。
最后,通过验证则关闭dialog,否则不关闭dialog并提示错误信息。

实现思路

dialog

mui提供了许多dialog,只有mui.prompt()提供了输入框,但它并不是密码框。
mui.confirm()的message参数,可以传html代码段来展示密码框,就选它了。

回调函数

由于当前版本mui,点击dialog中的按钮均会关闭dialog,所以需要对dialog按钮的默认行为进行修改。
注:下个版本会更新此修改,目前需要的话请下载附件中的mui.js文件。

验证密码

对用户输入的密码进行验证后,如果验证失败,则需要做出相应的提示。
和密码框的思路一样,使用一个文本内容默认为空的元素来展示错误信息。

功能实现

密码输入框

使用mui.confirm()弹出密码输入框。

mui.confirm('<input type="password" id="test" />', 'Hello MUI', null, function(e) {},'div');  

注:这里需要声明使用H5模式的dialog,参考文档dialog

阻止关闭dialog

用户输入完成后,点击”确认“按钮,验证密码。

mui.confirm('<input type="password" id="test" />', 'Hello MUI', null, function(event) {  
    var index = event.index;  
    if(index === 1) {  
        var pwd = document.getElementById('test').value;  
        // 验证失败返回false  
        return false;  
    }  
},'div');  

修改按钮的默认行为后,在回调函数中返回false,则不会关闭dialog。

错误信息

在拼接密码输入框的同时,见错误信息提示的元素一起拼接。

mui.confirm('<input type="password" id="test" /><span id="error">&nbsp</span>', 'Hello MUI', null, function(event) {},'div');  

源码

附上源码,直接浏览即可。

收起阅读 »

流应用体验视频及入口说明

流应用

流应用有多种入口来源,并非单一的应用市场搜索。

1. 使用DCloud流应用管理器

手机访问http://m3w.cn,可下载DCloud流应用管理器,获取和管理本机流应用。

2. 360手机助手搜索秒开流应用

2015年10月起的360手机助手起,支持搜索流应用名字,显示秒开按钮。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_i0171dyo7cf.html

3. 金立手机软件商店秒开流应用

2017年6月起的金立软件商店版本,可以在搜索页面下方推荐位及软件分类-即点即用里使用流应用。https://bbs.amigo.cn/forum.php?mod=viewthread&tid=217285
手机原厂支持的流应用,体验更优秀。

4. 360手机浏览器秒开流应用

2016年11月起,360手机浏览器8.0安卓版,开始内嵌流应用引擎。
在地址栏里敲vip.com,可以直接进入流应用。
使用时有3点注意:1.360浏览器会在WiFi下静默下载流应用插件,如果插件没下载完或不是在WiFi下,启动时仍然是普通H5。2. 普通H5和流应用的区别是,流应用顶部有一个黑色的导航条,没有地址栏。
https://v.qq.com/x/page/n0336208o73.html

5. 青柠桌面云文件夹

青柠桌面是国内较大的第三方laucher,其预置了流应用云文件夹,里面的应用即点即用又可以达到原生体验。实现了更高效率的分发变现。
可以点击这里下载体验

6. 快码,扫描立即秒装app

快码是一种集成了流应用、原生App下载、微信公众号关注、微博关注于一体的统一码。
快码是连接线上线下最便捷的方式。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_w0171ems73j.html

快码还具备扫码直通功能,扫码如下的码,能直接进入到大众点评外卖里的必胜客餐厅。

打通App孤岛,直达内容,这是HTML5及流应用的重要优势。

7. 分享,通过社交网络快速传播app

分享一个App,就像分享一个消息。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_r0171bswy6f.html

分享同样支持分享直通车,可以分享App里的具体内容, 比如:
一个资讯App的某条文章;
一个视频App的某个电影;
一个电商App的某个商品...

8. 推送流应用

推送是推广的大杀器,只要精准筛选目标用户,在合适的时间、给合适的人以合适的信息,点击推送后App立即安装激活。推广效率可以用“恐怖”来形容。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_x01833hx4q3.html

9. 手机网页打开流应用

这里有文章专门讲解如何通过wap浏览器打开流应用,把wap用户变成app用户。http://ask.dcloud.net.cn/article/579
视频如下:http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_t0190xh3198.html

10. 从一个App里打开流应用

app互推荐或应用内广告,也是流应用的流量来源。因为原生app的下载安装麻烦,所以一直以来积分墙等app互推业务并没有起量。但app向流应用导流的效果要好于向原生app数倍,重新打开了这个流量市场。
文档:http://ask.dcloud.net.cn/article/670

11. 清理卸载入口

360手机助手从2016年7月起的版本,在清理应用卸载时,会提示用户是否在桌面放一个微应用快捷方式图标在桌面。


每天有数千万人在清理卸载原生App。
非Top30的App,如果体积大、有后台耗电,很容易被用户清理掉。
原生Apk辛苦发展来的激活用户就此流失。
但有30%的用户在卸载后会点击保留微应用版本,实现低频应用的驻留。

继续阅读 »

流应用有多种入口来源,并非单一的应用市场搜索。

1. 使用DCloud流应用管理器

手机访问http://m3w.cn,可下载DCloud流应用管理器,获取和管理本机流应用。

2. 360手机助手搜索秒开流应用

2015年10月起的360手机助手起,支持搜索流应用名字,显示秒开按钮。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_i0171dyo7cf.html

3. 金立手机软件商店秒开流应用

2017年6月起的金立软件商店版本,可以在搜索页面下方推荐位及软件分类-即点即用里使用流应用。https://bbs.amigo.cn/forum.php?mod=viewthread&tid=217285
手机原厂支持的流应用,体验更优秀。

4. 360手机浏览器秒开流应用

2016年11月起,360手机浏览器8.0安卓版,开始内嵌流应用引擎。
在地址栏里敲vip.com,可以直接进入流应用。
使用时有3点注意:1.360浏览器会在WiFi下静默下载流应用插件,如果插件没下载完或不是在WiFi下,启动时仍然是普通H5。2. 普通H5和流应用的区别是,流应用顶部有一个黑色的导航条,没有地址栏。
https://v.qq.com/x/page/n0336208o73.html

5. 青柠桌面云文件夹

青柠桌面是国内较大的第三方laucher,其预置了流应用云文件夹,里面的应用即点即用又可以达到原生体验。实现了更高效率的分发变现。
可以点击这里下载体验

6. 快码,扫描立即秒装app

快码是一种集成了流应用、原生App下载、微信公众号关注、微博关注于一体的统一码。
快码是连接线上线下最便捷的方式。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_w0171ems73j.html

快码还具备扫码直通功能,扫码如下的码,能直接进入到大众点评外卖里的必胜客餐厅。

打通App孤岛,直达内容,这是HTML5及流应用的重要优势。

7. 分享,通过社交网络快速传播app

分享一个App,就像分享一个消息。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_r0171bswy6f.html

分享同样支持分享直通车,可以分享App里的具体内容, 比如:
一个资讯App的某条文章;
一个视频App的某个电影;
一个电商App的某个商品...

8. 推送流应用

推送是推广的大杀器,只要精准筛选目标用户,在合适的时间、给合适的人以合适的信息,点击推送后App立即安装激活。推广效率可以用“恐怖”来形容。
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_x01833hx4q3.html

9. 手机网页打开流应用

这里有文章专门讲解如何通过wap浏览器打开流应用,把wap用户变成app用户。http://ask.dcloud.net.cn/article/579
视频如下:http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_t0190xh3198.html

10. 从一个App里打开流应用

app互推荐或应用内广告,也是流应用的流量来源。因为原生app的下载安装麻烦,所以一直以来积分墙等app互推业务并没有起量。但app向流应用导流的效果要好于向原生app数倍,重新打开了这个流量市场。
文档:http://ask.dcloud.net.cn/article/670

11. 清理卸载入口

360手机助手从2016年7月起的版本,在清理应用卸载时,会提示用户是否在桌面放一个微应用快捷方式图标在桌面。


每天有数千万人在清理卸载原生App。
非Top30的App,如果体积大、有后台耗电,很容易被用户清理掉。
原生Apk辛苦发展来的激活用户就此流失。
但有30%的用户在卸载后会点击保留微应用版本,实现低频应用的驻留。

收起阅读 »

Deferred long-running timer task(s)...

Deferred long-running timer task(s) to improve scrolling smoothness. See crbug.com/574343

Deferred long-running timer task(s) to improve scrolling smoothness. See crbug.com/574343

Mui前端架子(编程规范分享)

mui

原文标题:PHP Lumen - 入门教程 - web前端架子
转来自我的博客:http://blog.csdn.net/wowkk/article/details/52254696

用了Lumen一段时间了,感觉还不错。也适合全栈开发。因为我一丢丢PHP基础都没看就直接用起了框架,挺多地方还是闹笑话了。比如,字符串追加,PHP它喵的居然是用 “.” 来追加,而通过“->”进行属性调用也是不爽~

这个web前端架子,不是Lumen专用的,额外分享。

首先我写了一个公共类(common.js),主要用来进行封装请求的。

/*!  
 * =====================================================  
 * 全局通用变量  
 * =====================================================  
 */  
var Common = {};  
//Common.ServerUrl = "http://120.24.xx.xx:8080/";       //线上测试版本  
Common.ServerUrl = "http://192.168.0.110:8080/";    //公司测试版本  
//Common.ServerUrl = "http://192.168.99.139:8080/";     //宿舍测试版本  

Common.Post = function(url,data,successcallback,errcallback){  
    console.log(Common.jsonToUrl(url,data));  
    if(errcallback==null){  
        errcallback = function(xhr,type,errorThrown){  
            console.log(JSON.stringify(xhr))  
            plus.nativeUI.closeWaiting();//关闭旋转菊花  
            alert("网络异常:" + url);  
        }  
    }  
    //这里的mui是HBuilder跨平台开发工具自己的js,根据自己项目调改。  
    mui.ajax(Common.ServerUrl + url,{  
        data:data,  
        dataType:'json',  
        type:'post',  
        timeout:5000,  
        success:successcallback,  
        error:errcallback  
    });  
}  

Common.jsonToUrl=function(url,jsonData){  
    var full_url = Common.ServerUrl + url + "?";  
    for(var index in jsonData){  
        full_url = full_url + index + "=" + jsonData[index] + "&";  
    }  
    return full_url;  
};

可以把这段代码塞到js插件里面去(比如jQuery)减少请求。
这一丢丢代码有几个好处:
1.统一请求的url,不需要每个页面都去设置请求地址。页面发送ajax时,只需要把相对路径传进来就行了。
2.统一错误返回的处理,可以即时知道哪个请求出错。也可以根据需要特殊回调处理。
3.把post的data转换为url地址,方便直接复制到浏览器进行get调试。
4.方便拓展与维护,比如可以统一处理“未登录则自动跳转到登录页”。

再看下html页的代码

<script>  
        /*  
         * 页面配置  
         */  
        var PAGE = {  
                View: {},  
                page: 0,  
                Model: {  
                    Article: function(article) {  
                        return '<article id="' + article.information_id + '">' +  
                            '<div class="article-time">' +  
                            '<span>' + article.time_title + '</span>' +  
                            '</div>' +  
                            '<div class="article-bg" style="background-image: url(' + article.information_imgurl + ');">' +  
                            '<div class="article-bg-cover">' +  
                            '<span class="information_title"># ' + article.information_title + '</span>' +  
                            '</div>' +  
                            '</div>' +  
                            '<div class="mui-pull-right article_collect">' +  
                            '<img style="width: 100%;" src="../../img/news_shoucang.png" />' +  
                            '<div class="article_collect_fone">' + article.favour_num + '</div>' +  
                            '</div>' +  
                            '</article>';  
                    },  
                    Articles:function(articles){  
                        var html = "";  
                        for(var i = 0; i < articles.length; i++) {  
                            html += PAGE.Model.Article(articles[i]);  
                        }  
                        return html;  
                    }  
                }  
            };  
        mui.init();//(mui框架需要)初始化框架  
        mui.plusReady(function() {  
            PAGE.Init();//初始化本页面  
        });  
        /*  
         * 页面初始化  
         */  
        PAGE.Init = function() {  
                PAGE.preloadView();  
                PAGE.addEventListener();  
            }  
            /*  
             * 页面预加载  
             */  
        PAGE.preloadView = function() {}  
            /*  
             * 事件监听  
             */  
        PAGE.addEventListener = function() {  
            PAGE.addEventListener_Article();//确定监听点击文章列表的元素  
        }  
            /*  
             * 页面预加载-实现  
             */  
        PAGE.preloadView_Name = function() {}  
            /*  
             * 事件监听-实现  
             */  
        PAGE.addEventListener_Article = function() {  
                mui("#div_newList").on("tap", "article", function() {  
                    mui.openWindow({  
                        id: "/View/News/details.html",  
                        url: "/View/News/details.html",  
                        extras: {  
                            information_id: this.id,  
                            information_title: this.getElementsByClassName("information_title")[0].innerText,  
                            information_imgurl: this.getElementsByClassName("article-bg")[0].style.backgroundImage  
                        }  
                    })  
                })  
            }  
            /*  
             * 事件实现  
             */  
        PAGE.Event_Name = function() {}  
    </script>

编出来的这段,个人用起来还是比较舒服的。
1.所有js代码都是在PAGE这个域里面,尽量避免污染。
2.将所有监听事件独个封装起来,然后由PAGE.addEventListener统一调用。这样在简单事件较多的情况下,代码也足够清晰易阅读和定位。
3.所有动态生成的代码放在PAGE.Model对象里面(传人json数据,返回对应的html代码)。同样也是清晰易阅读和定位。
4.普通函数比如,更新页面数据就用PAGE.Event_XXX格式命名函数。这个主要就是统一规范吧。
5.一些配置变量,比如当前页PageNum,也可以防止PAGE里面去维护。

接下来继续实战,看能不能怎么优化。现在为了性能,大多数都是用原生js,看看有没有机会封装个js架子。

继续阅读 »

原文标题:PHP Lumen - 入门教程 - web前端架子
转来自我的博客:http://blog.csdn.net/wowkk/article/details/52254696

用了Lumen一段时间了,感觉还不错。也适合全栈开发。因为我一丢丢PHP基础都没看就直接用起了框架,挺多地方还是闹笑话了。比如,字符串追加,PHP它喵的居然是用 “.” 来追加,而通过“->”进行属性调用也是不爽~

这个web前端架子,不是Lumen专用的,额外分享。

首先我写了一个公共类(common.js),主要用来进行封装请求的。

/*!  
 * =====================================================  
 * 全局通用变量  
 * =====================================================  
 */  
var Common = {};  
//Common.ServerUrl = "http://120.24.xx.xx:8080/";       //线上测试版本  
Common.ServerUrl = "http://192.168.0.110:8080/";    //公司测试版本  
//Common.ServerUrl = "http://192.168.99.139:8080/";     //宿舍测试版本  

Common.Post = function(url,data,successcallback,errcallback){  
    console.log(Common.jsonToUrl(url,data));  
    if(errcallback==null){  
        errcallback = function(xhr,type,errorThrown){  
            console.log(JSON.stringify(xhr))  
            plus.nativeUI.closeWaiting();//关闭旋转菊花  
            alert("网络异常:" + url);  
        }  
    }  
    //这里的mui是HBuilder跨平台开发工具自己的js,根据自己项目调改。  
    mui.ajax(Common.ServerUrl + url,{  
        data:data,  
        dataType:'json',  
        type:'post',  
        timeout:5000,  
        success:successcallback,  
        error:errcallback  
    });  
}  

Common.jsonToUrl=function(url,jsonData){  
    var full_url = Common.ServerUrl + url + "?";  
    for(var index in jsonData){  
        full_url = full_url + index + "=" + jsonData[index] + "&";  
    }  
    return full_url;  
};

可以把这段代码塞到js插件里面去(比如jQuery)减少请求。
这一丢丢代码有几个好处:
1.统一请求的url,不需要每个页面都去设置请求地址。页面发送ajax时,只需要把相对路径传进来就行了。
2.统一错误返回的处理,可以即时知道哪个请求出错。也可以根据需要特殊回调处理。
3.把post的data转换为url地址,方便直接复制到浏览器进行get调试。
4.方便拓展与维护,比如可以统一处理“未登录则自动跳转到登录页”。

再看下html页的代码

<script>  
        /*  
         * 页面配置  
         */  
        var PAGE = {  
                View: {},  
                page: 0,  
                Model: {  
                    Article: function(article) {  
                        return '<article id="' + article.information_id + '">' +  
                            '<div class="article-time">' +  
                            '<span>' + article.time_title + '</span>' +  
                            '</div>' +  
                            '<div class="article-bg" style="background-image: url(' + article.information_imgurl + ');">' +  
                            '<div class="article-bg-cover">' +  
                            '<span class="information_title"># ' + article.information_title + '</span>' +  
                            '</div>' +  
                            '</div>' +  
                            '<div class="mui-pull-right article_collect">' +  
                            '<img style="width: 100%;" src="../../img/news_shoucang.png" />' +  
                            '<div class="article_collect_fone">' + article.favour_num + '</div>' +  
                            '</div>' +  
                            '</article>';  
                    },  
                    Articles:function(articles){  
                        var html = "";  
                        for(var i = 0; i < articles.length; i++) {  
                            html += PAGE.Model.Article(articles[i]);  
                        }  
                        return html;  
                    }  
                }  
            };  
        mui.init();//(mui框架需要)初始化框架  
        mui.plusReady(function() {  
            PAGE.Init();//初始化本页面  
        });  
        /*  
         * 页面初始化  
         */  
        PAGE.Init = function() {  
                PAGE.preloadView();  
                PAGE.addEventListener();  
            }  
            /*  
             * 页面预加载  
             */  
        PAGE.preloadView = function() {}  
            /*  
             * 事件监听  
             */  
        PAGE.addEventListener = function() {  
            PAGE.addEventListener_Article();//确定监听点击文章列表的元素  
        }  
            /*  
             * 页面预加载-实现  
             */  
        PAGE.preloadView_Name = function() {}  
            /*  
             * 事件监听-实现  
             */  
        PAGE.addEventListener_Article = function() {  
                mui("#div_newList").on("tap", "article", function() {  
                    mui.openWindow({  
                        id: "/View/News/details.html",  
                        url: "/View/News/details.html",  
                        extras: {  
                            information_id: this.id,  
                            information_title: this.getElementsByClassName("information_title")[0].innerText,  
                            information_imgurl: this.getElementsByClassName("article-bg")[0].style.backgroundImage  
                        }  
                    })  
                })  
            }  
            /*  
             * 事件实现  
             */  
        PAGE.Event_Name = function() {}  
    </script>

编出来的这段,个人用起来还是比较舒服的。
1.所有js代码都是在PAGE这个域里面,尽量避免污染。
2.将所有监听事件独个封装起来,然后由PAGE.addEventListener统一调用。这样在简单事件较多的情况下,代码也足够清晰易阅读和定位。
3.所有动态生成的代码放在PAGE.Model对象里面(传人json数据,返回对应的html代码)。同样也是清晰易阅读和定位。
4.普通函数比如,更新页面数据就用PAGE.Event_XXX格式命名函数。这个主要就是统一规范吧。
5.一些配置变量,比如当前页PageNum,也可以防止PAGE里面去维护。

接下来继续实战,看能不能怎么优化。现在为了性能,大多数都是用原生js,看看有没有机会封装个js架子。

收起阅读 »