HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

一个底部选项卡的实现(webview模式)

选项卡

直接上代码吧。
自行修改正确的资源文件路径(此例子直接放在默认目录下,同级目录放tab-*.html)

<!--  main.html 入口文件 -->  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title>选项卡演示</title>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style>  
        </style>  
    </head>  

    <body>  
        <div class="mui-content">  
            <nav id="bar" class="mui-bar mui-bar-tab">  
                <a class="mui-tab-item mui-active" href="tab-main.html" data-id="main">  
                    <span class="mui-icon mui-icon-home"></span>  
                    <span class="mui-tab-label">首页</span>  
                </a>  
                <a class="mui-tab-item" href="tab-message.html" data-id="message">  
                    <span class="mui-icon mui-icon-email"></span>  
                    <span class="mui-tab-label">消息</span>  
                </a>  
                <a class="mui-tab-item" href="tab-contact.html" data-id="contact">  
                    <span class="mui-icon mui-icon-contact"></span>  
                    <span class="mui-tab-label">通讯录</span>  
                </a>  
                <a class="mui-tab-item" href="tab-setting.html" data-id="setting">  
                    <span class="mui-icon mui-icon-gear"></span>  
                    <span class="mui-tab-label">设置</span>  
                </a>  
            </nav>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script>  
            mui.init();  
            mui.plusReady(function() {  
                var self = plus.webview.currentWebview();  
                var current = '';  
                var styles = {  
                    top: '0',  
                    bottom: '51px'  
                };  
                var tabsConfig = {  
                    main: {  
                        url: 'tab-main.html',  
                        styles: styles,  
                        default: true  
                    },  
                    message: {  
                        url: 'tab-message.html',  
                        styles: styles  
                    },  
                    contact: {  
                        url: 'tab-contact.html',  
                        styles: styles  
                    },  
                    setting: {  
                        url: 'tab-setting.html',  
                        styles: styles  
                    }  
                };  
                var tabs = {};  
                for (id in tabsConfig) {  
                    tabs[id] = plus.webview.create(tabsConfig[id].url, id, tabsConfig[id].styles);  
                    if (tabsConfig[id]['default']) {  
                        self.append(tabs[id]);  
                        current = id;  
                    }  
                }  
                mui('#bar').on('tap', 'a', function(e) {  
                    if (current == this.dataset.id) {  
                        mui.fire(tabs[current], 'scroll2top');  
                        return;  
                    }  
                    tabs[this.dataset.id].show();  
                    tabs[current].hide();  
                    current = this.dataset.id;  
                });  
            });  
        </script>  
    </body>  
</html>
<!-- tab-*.html 举例-->  
<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
    <title>此处就是显示的标题</title>  
    <script src="js/mui.min.js"></script>  
    <link href="css/mui.min.css" rel="stylesheet"/>  
    <script type="text/javascript" charset="UTF-8">  
        mui.init();  
    </script>  
</head>  
<body>  
    <div class="mui-content">  
        <p>示例页面,此页面内容正常写,标题就是标签页的标题。</p>  
    </div>  
</body>  
</html>

更新:上传了一个完整的例子~ 懒人最爱~

继续阅读 »

直接上代码吧。
自行修改正确的资源文件路径(此例子直接放在默认目录下,同级目录放tab-*.html)

<!--  main.html 入口文件 -->  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title>选项卡演示</title>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style>  
        </style>  
    </head>  

    <body>  
        <div class="mui-content">  
            <nav id="bar" class="mui-bar mui-bar-tab">  
                <a class="mui-tab-item mui-active" href="tab-main.html" data-id="main">  
                    <span class="mui-icon mui-icon-home"></span>  
                    <span class="mui-tab-label">首页</span>  
                </a>  
                <a class="mui-tab-item" href="tab-message.html" data-id="message">  
                    <span class="mui-icon mui-icon-email"></span>  
                    <span class="mui-tab-label">消息</span>  
                </a>  
                <a class="mui-tab-item" href="tab-contact.html" data-id="contact">  
                    <span class="mui-icon mui-icon-contact"></span>  
                    <span class="mui-tab-label">通讯录</span>  
                </a>  
                <a class="mui-tab-item" href="tab-setting.html" data-id="setting">  
                    <span class="mui-icon mui-icon-gear"></span>  
                    <span class="mui-tab-label">设置</span>  
                </a>  
            </nav>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script>  
            mui.init();  
            mui.plusReady(function() {  
                var self = plus.webview.currentWebview();  
                var current = '';  
                var styles = {  
                    top: '0',  
                    bottom: '51px'  
                };  
                var tabsConfig = {  
                    main: {  
                        url: 'tab-main.html',  
                        styles: styles,  
                        default: true  
                    },  
                    message: {  
                        url: 'tab-message.html',  
                        styles: styles  
                    },  
                    contact: {  
                        url: 'tab-contact.html',  
                        styles: styles  
                    },  
                    setting: {  
                        url: 'tab-setting.html',  
                        styles: styles  
                    }  
                };  
                var tabs = {};  
                for (id in tabsConfig) {  
                    tabs[id] = plus.webview.create(tabsConfig[id].url, id, tabsConfig[id].styles);  
                    if (tabsConfig[id]['default']) {  
                        self.append(tabs[id]);  
                        current = id;  
                    }  
                }  
                mui('#bar').on('tap', 'a', function(e) {  
                    if (current == this.dataset.id) {  
                        mui.fire(tabs[current], 'scroll2top');  
                        return;  
                    }  
                    tabs[this.dataset.id].show();  
                    tabs[current].hide();  
                    current = this.dataset.id;  
                });  
            });  
        </script>  
    </body>  
</html>
<!-- tab-*.html 举例-->  
<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
    <title>此处就是显示的标题</title>  
    <script src="js/mui.min.js"></script>  
    <link href="css/mui.min.css" rel="stylesheet"/>  
    <script type="text/javascript" charset="UTF-8">  
        mui.init();  
    </script>  
</head>  
<body>  
    <div class="mui-content">  
        <p>示例页面,此页面内容正常写,标题就是标签页的标题。</p>  
    </div>  
</body>  
</html>

更新:上传了一个完整的例子~ 懒人最爱~

收起阅读 »

CSS 自动验证格式化排序 一行一条 [新]

css 格式化

HBuilderX 的 CSS格式化使用 js-beautify 插件, 这玩意不能格式化成一行,现提供新的的方法。

官方插件市场安装插件 validate-stylelint
该插件在 保存时 进行语法校验,提示错误,自动修复 。我们可借助 [一行规则+自动修复]来自动格式化,并增加一个排序功能。
截至 v1.0.6 版本 没有开启【自动修复】,暂需自行修改插件。若插件更新并开启自动修复,可忽略修改步骤。

安装后 ,插件文件夹 x:\HBuilderX\plugins\validate-stylelint

1、改造插件,开启自动修复,添加排序插件
修改文件 package.json
1-1、在命令数组最后添加个 "--fix" 参数 开启修复

 "command": [  
    ....  
    "${pluginPath}",  
    "${file}", // 逗号分隔  
    "--fix"  // 这里添加    
]

1-2、添加排序插件

"dependencies": {  
    .....  
    "stylelint-config-standard": "^18.2.0",  
    "stylelint-config-recess-order": "^2.4.0"  // 添加  
}

validate-stylelint 文件夹下执行 [ npm up ] 更新依赖

2、新增排序扩展 和 一行 规则

修改规则文件 .stylelintrc.js

"extends": [  
    "stylelint-config-recommended",  
    "stylelint-config-recess-order"  // 添加  
],  
"rules": {  
     // 自定义一行规则 见附件  
}
h1,  
h2{  
    color:#fff;  
    margin-top: 0;  
    top: 10px;  
}  
// 自动格式化+排序  
h1, h2{ top: 10px; margin-top: 0; color:#fff;}
继续阅读 »

HBuilderX 的 CSS格式化使用 js-beautify 插件, 这玩意不能格式化成一行,现提供新的的方法。

官方插件市场安装插件 validate-stylelint
该插件在 保存时 进行语法校验,提示错误,自动修复 。我们可借助 [一行规则+自动修复]来自动格式化,并增加一个排序功能。
截至 v1.0.6 版本 没有开启【自动修复】,暂需自行修改插件。若插件更新并开启自动修复,可忽略修改步骤。

安装后 ,插件文件夹 x:\HBuilderX\plugins\validate-stylelint

1、改造插件,开启自动修复,添加排序插件
修改文件 package.json
1-1、在命令数组最后添加个 "--fix" 参数 开启修复

 "command": [  
    ....  
    "${pluginPath}",  
    "${file}", // 逗号分隔  
    "--fix"  // 这里添加    
]

1-2、添加排序插件

"dependencies": {  
    .....  
    "stylelint-config-standard": "^18.2.0",  
    "stylelint-config-recess-order": "^2.4.0"  // 添加  
}

validate-stylelint 文件夹下执行 [ npm up ] 更新依赖

2、新增排序扩展 和 一行 规则

修改规则文件 .stylelintrc.js

"extends": [  
    "stylelint-config-recommended",  
    "stylelint-config-recess-order"  // 添加  
],  
"rules": {  
     // 自定义一行规则 见附件  
}
h1,  
h2{  
    color:#fff;  
    margin-top: 0;  
    top: 10px;  
}  
// 自动格式化+排序  
h1, h2{ top: 10px; margin-top: 0; color:#fff;}
收起阅读 »

在哪里可以学习整套的MUI 和Hbuilder 课程?

mui HBuilder

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!咨询报名QQ:410355878 网址:http://www.dongyixueyuan.com/ 欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

学习前常见的问题有哪些,下面做了详细的介绍!
1.VIP课时时间多久?
2.学费多少?
3.线上线下?
4.能够给予实践指导吗?
5.需要什么基础吗?(我现在是前端开发,有JAVA基础)
6.有什么优惠吗?
7.上课时间?
8.一遍听不会,可以重复看吗?
9.有问题有专们的老师解答吗,还是留言等老师解答?
10.如果老师回答问题,一般多久会回复,这么多人能顾得上回答我的问题吗?

1.vip课程报名后终身学习,循环开班,每一期周期是1-2个月,根据学员掌握情况和APP开发实战项目教学进行微调(每一期都会讲一个不一样的APP开发项目)
2.学费3800元 这一期报名有求职季活动,减300 并且有相关福利赠送
3.线上学习,在腾讯课堂教学
4.可以的 实战项目开发 在高级课程部分
5.零基础可以学习 不需要太高的编程基础
6.优惠在第2条已说明了哦
7.每周一至周六 晚上8点-10点 突发情况或节假日顺延或者微调
8.无限重修
9.有专门老师解答 分为前端课程 UI课程 高级实战课程 分别有两位专业老师解答 工作日上午10点-下午6点 晚上上课可以在课堂直接提问
10.小班授课,保证每一位同学都可以得到老师的辅导,每一期我们在10人左右 ,一位老师辅导5位同学。

继续阅读 »

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!咨询报名QQ:410355878 网址:http://www.dongyixueyuan.com/ 欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

学习前常见的问题有哪些,下面做了详细的介绍!
1.VIP课时时间多久?
2.学费多少?
3.线上线下?
4.能够给予实践指导吗?
5.需要什么基础吗?(我现在是前端开发,有JAVA基础)
6.有什么优惠吗?
7.上课时间?
8.一遍听不会,可以重复看吗?
9.有问题有专们的老师解答吗,还是留言等老师解答?
10.如果老师回答问题,一般多久会回复,这么多人能顾得上回答我的问题吗?

1.vip课程报名后终身学习,循环开班,每一期周期是1-2个月,根据学员掌握情况和APP开发实战项目教学进行微调(每一期都会讲一个不一样的APP开发项目)
2.学费3800元 这一期报名有求职季活动,减300 并且有相关福利赠送
3.线上学习,在腾讯课堂教学
4.可以的 实战项目开发 在高级课程部分
5.零基础可以学习 不需要太高的编程基础
6.优惠在第2条已说明了哦
7.每周一至周六 晚上8点-10点 突发情况或节假日顺延或者微调
8.无限重修
9.有专门老师解答 分为前端课程 UI课程 高级实战课程 分别有两位专业老师解答 工作日上午10点-下午6点 晚上上课可以在课堂直接提问
10.小班授课,保证每一位同学都可以得到老师的辅导,每一期我们在10人左右 ,一位老师辅导5位同学。

收起阅读 »

修改PopPicker 增加动态级联能力。

mui

主要思路是增加一个change入口, 当选项发生改变时可以触发自己的级联逻辑。

var province = new mui.PopPicker(  
            {layer: 3,  
                //change  
                changeFn:function(even){  
                    //change 自己的逻辑  
                                       var nextPickerElement = this.nextSibling;  
                    if (nextPickerElement && nextPickerElement.picker) {  
                        var eventData = event.detail || {};  
                        var preItem = eventData.item || {};  
                        if (preItem.type == 'province'){  
                            nextPickerElement.picker.setItems(getCascadeData("cities", preItem.value));  
                        } else if (preItem.type == 'cities'){  
                            nextPickerElement.picker.setItems(getCascadeData("counties", preItem.value));  
                        }  
                    }  
                }  
            });
var PopPicker = $.PopPicker = $.Class.extend({  
        //构造函数  
        init: function(options) {  
            var self = this;  
            self.options = options || {};  
            self.options.buttons = self.options.buttons || ['取消', '确定'];  
            self.panel = $.dom(panelBuffer)[0];  
            document.body.appendChild(self.panel);  
            self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');  
            self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');  
            self.body = self.panel.querySelector('.mui-poppicker-body');  
            self.mask = $.createMask();  
            self.cancel.innerText = self.options.buttons[0];  
            self.ok.innerText = self.options.buttons[1];  
            self.cancel.addEventListener('tap', function(event) {  
                self.hide();  
            }, false);  
            self.ok.addEventListener('tap', function(event) {  
                if (self.callback) {  
                    var rs = self.callback(self.getSelectedItems());  
                    if (rs !== false) {  
                        self.hide();  
                    }  
                }  
            }, false);  

            **self.changeFn = self.options.changeFn || function(event) {  
                var nextPickerElement = this.nextSibling;  
                if (nextPickerElement && nextPickerElement.picker) {  
                    var eventData = event.detail || {};  
                    var preItem = eventData.item || {};  
                    nextPickerElement.picker.setItems(preItem.children);  
                }  
            };**  

            self.mask[0].addEventListener('tap', function() {  
                self.hide();  
            }, false);  
            self._createPicker();  
            //防止滚动穿透  
            self.panel.addEventListener('touchstart', function(event) {  
                event.preventDefault();  
            }, false);  
            self.panel.addEventListener('touchmove', function(event) {  
                event.preventDefault();  
            }, false);  
        },  
        _createPicker: function() {  
            var self = this;  
            var layer = self.options.layer || 1;  
            var width = (100 / layer) + '%';  
            self.pickers = [];  
            for (var i = 1; i <= layer; i++) {  
                var pickerElement = $.dom(pickerBuffer)[0];  
                pickerElement.style.width = width;  
                self.body.appendChild(pickerElement);  
                var picker = $(pickerElement).picker();  
                self.pickers.push(picker);  
                pickerElement.addEventListener('change', self.changeFn, false);  
            }  
        },  
        //填充数据  
        setData: function(data) {  
            var self = this;  
            data = data || [];  
            self.pickers[0].setItems(data);  
        },  
        //获取选中的项(数组)  
        getSelectedItems: function() {  
            var self = this;  
            var items = [];  
            for (var i in self.pickers) {  
                var picker = self.pickers[i];  
                items.push(picker.getSelectedItem() || {});  
            }  
            return items;  
        },  
        //显示  
        show: function(callback) {  
            var self = this;  
            self.callback = callback;  
            self.mask.show();  
            document.body.classList.add($.className('poppicker-active-for-page'));  
            self.panel.classList.add($.className('active'));  
            //处理物理返回键  
            self.__back = $.back;  
            $.back = function() {  
                self.hide();  
            };  
        },  
        //隐藏  
        hide: function() {  
            var self = this;  
            if (self.disposed) return;  
            self.panel.classList.remove($.className('active'));  
            self.mask.close();  
            document.body.classList.remove($.className('poppicker-active-for-page'));  
            //处理物理返回键  
            $.back=self.__back;  
        },  
        dispose: function() {  
            var self = this;  
            self.hide();  
            setTimeout(function() {  
                self.panel.parentNode.removeChild(self.panel);  
                for (var name in self) {  
                    self[name] = null;  
                    delete self[name];  
                };  
                self.disposed = true;  
            }, 300);  
        }  
    });
继续阅读 »

主要思路是增加一个change入口, 当选项发生改变时可以触发自己的级联逻辑。

var province = new mui.PopPicker(  
            {layer: 3,  
                //change  
                changeFn:function(even){  
                    //change 自己的逻辑  
                                       var nextPickerElement = this.nextSibling;  
                    if (nextPickerElement && nextPickerElement.picker) {  
                        var eventData = event.detail || {};  
                        var preItem = eventData.item || {};  
                        if (preItem.type == 'province'){  
                            nextPickerElement.picker.setItems(getCascadeData("cities", preItem.value));  
                        } else if (preItem.type == 'cities'){  
                            nextPickerElement.picker.setItems(getCascadeData("counties", preItem.value));  
                        }  
                    }  
                }  
            });
var PopPicker = $.PopPicker = $.Class.extend({  
        //构造函数  
        init: function(options) {  
            var self = this;  
            self.options = options || {};  
            self.options.buttons = self.options.buttons || ['取消', '确定'];  
            self.panel = $.dom(panelBuffer)[0];  
            document.body.appendChild(self.panel);  
            self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');  
            self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');  
            self.body = self.panel.querySelector('.mui-poppicker-body');  
            self.mask = $.createMask();  
            self.cancel.innerText = self.options.buttons[0];  
            self.ok.innerText = self.options.buttons[1];  
            self.cancel.addEventListener('tap', function(event) {  
                self.hide();  
            }, false);  
            self.ok.addEventListener('tap', function(event) {  
                if (self.callback) {  
                    var rs = self.callback(self.getSelectedItems());  
                    if (rs !== false) {  
                        self.hide();  
                    }  
                }  
            }, false);  

            **self.changeFn = self.options.changeFn || function(event) {  
                var nextPickerElement = this.nextSibling;  
                if (nextPickerElement && nextPickerElement.picker) {  
                    var eventData = event.detail || {};  
                    var preItem = eventData.item || {};  
                    nextPickerElement.picker.setItems(preItem.children);  
                }  
            };**  

            self.mask[0].addEventListener('tap', function() {  
                self.hide();  
            }, false);  
            self._createPicker();  
            //防止滚动穿透  
            self.panel.addEventListener('touchstart', function(event) {  
                event.preventDefault();  
            }, false);  
            self.panel.addEventListener('touchmove', function(event) {  
                event.preventDefault();  
            }, false);  
        },  
        _createPicker: function() {  
            var self = this;  
            var layer = self.options.layer || 1;  
            var width = (100 / layer) + '%';  
            self.pickers = [];  
            for (var i = 1; i <= layer; i++) {  
                var pickerElement = $.dom(pickerBuffer)[0];  
                pickerElement.style.width = width;  
                self.body.appendChild(pickerElement);  
                var picker = $(pickerElement).picker();  
                self.pickers.push(picker);  
                pickerElement.addEventListener('change', self.changeFn, false);  
            }  
        },  
        //填充数据  
        setData: function(data) {  
            var self = this;  
            data = data || [];  
            self.pickers[0].setItems(data);  
        },  
        //获取选中的项(数组)  
        getSelectedItems: function() {  
            var self = this;  
            var items = [];  
            for (var i in self.pickers) {  
                var picker = self.pickers[i];  
                items.push(picker.getSelectedItem() || {});  
            }  
            return items;  
        },  
        //显示  
        show: function(callback) {  
            var self = this;  
            self.callback = callback;  
            self.mask.show();  
            document.body.classList.add($.className('poppicker-active-for-page'));  
            self.panel.classList.add($.className('active'));  
            //处理物理返回键  
            self.__back = $.back;  
            $.back = function() {  
                self.hide();  
            };  
        },  
        //隐藏  
        hide: function() {  
            var self = this;  
            if (self.disposed) return;  
            self.panel.classList.remove($.className('active'));  
            self.mask.close();  
            document.body.classList.remove($.className('poppicker-active-for-page'));  
            //处理物理返回键  
            $.back=self.__back;  
        },  
        dispose: function() {  
            var self = this;  
            self.hide();  
            setTimeout(function() {  
                self.panel.parentNode.removeChild(self.panel);  
                for (var name in self) {  
                    self[name] = null;  
                    delete self[name];  
                };  
                self.disposed = true;  
            }, 300);  
        }  
    });
收起阅读 »

指令集支持

建议指令集支持到armv7s,方便使用,否则工程本身需要支持到armv7s时,导入sdk很是不方便

建议指令集支持到armv7s,方便使用,否则工程本身需要支持到armv7s时,导入sdk很是不方便

边改边看、浏览器运行如何查看asp、jsp文件

浏览器运行 边改边看 JSP ASP

在HBuilde里运行asp、jsp文件需要设置这些文件使用何种服务器打开
配置如下:
工具-选项-HBuilder-web服务器,选择asp类文件、jsp类文件使用服务器类型


也可以在边改边看最左边设置处修改,如下图

继续阅读 »

在HBuilde里运行asp、jsp文件需要设置这些文件使用何种服务器打开
配置如下:
工具-选项-HBuilder-web服务器,选择asp类文件、jsp类文件使用服务器类型


也可以在边改边看最左边设置处修改,如下图

收起阅读 »

HBuilder模板语法提示说明

代码助手

HBuilder7.1起支持模板语法提示。
模板语法提示,指对angularjs、vue等框架的html模板{{}}内语法的提示
目前暂时实现了对已编写的html模板内出现的单词进行提示。提示方式如下
如下图所示,项目中存在9个vue模板


其中filter.vue内有{{item.title}}、{{option.value}}等内容

在其他的vue文件的{{}}内,可对item、title、option、vaule等内容进行提示,如下图

继续阅读 »

HBuilder7.1起支持模板语法提示。
模板语法提示,指对angularjs、vue等框架的html模板{{}}内语法的提示
目前暂时实现了对已编写的html模板内出现的单词进行提示。提示方式如下
如下图所示,项目中存在9个vue模板


其中filter.vue内有{{item.title}}、{{option.value}}等内容

在其他的vue文件的{{}}内,可对item、title、option、vaule等内容进行提示,如下图

收起阅读 »

为何那么多一线互联网公司做流应用?

流应用

流应用是一个很多人不太容易理解的新概念,从去年大众点评外卖流应用上线时,很多人就不理解:

  1. 大众点评有原生版,为何又单独立项做流应用?成本增加了啊;
  2. 为何要做一个只能在360手助发行的版本?获取用户的潜在基数小了啊。

流应用接下来的发展就让人“更难理解”了,京东、360、有道、唯品会、携程、去哪儿、途牛、驴妈妈、神州专车、蘑菇街、当当、e代驾、卖座电影、爱鲜蜂…这些一线互联网公司怎么都在做流应用?
连做游戏的也进来了,传奇世界流应用也上线了,DCloud并没有专用游戏引擎,他们干啥呢?

其实不止是这些厂家,按目前的业务发展速度,预计年内主流的互联网App大多都会有流应用版本。

有人怀疑难道360手助强压开发商做流应用?然后由DCloud为其外包开发?
当然也不是,大家做流应用都是自愿投人投钱做,有的公司的流应用团队还不小,市场、产品、技术、运营、测试组成十几人的团队负责流应用项目。

可是流应用到底有什么魅力把这些大公司们纷纷卷进来呢?
还有,DCloud一直说面向开发者免费,工具免费、自己也不接项目开发,它怎么挣钱,它到底想干啥?
这个问题这几年一直被人问,现在也该解释了。

开发者做App,目的不是“做App”,而是给移动互联网用户提供服务。
如何获取用户、获得订单、持续复购或持续看广告?这是更根本的问题。
DCloud给开发者提供的,是一个基于HTML5的、从开发到获取用户到持续商业变现的全流程闭环生态。
并且是一个获客成本、用户质量、运营指标比原生生态更优质的新生态。
具体来讲,

  1. 获客成本低
    一个原生app的下载成本几元、激活成本十几元,新客几十元。而流应用可以把这个成本下降数倍。
  2. 获客质量不变
    流应用因为能达到原生的功能和体验,其留存、注册转换、订单转换、复购率等各项指标与原生app并无差别。DCloud为流应用开发者提供了专业的运营报表分析系统,可协助开发者优化各项业务指标。
  3. 获客数量多
    为什么流应用目前只有360手助上能搜索到,就能有足够多用户量来满足一线互联网公司的胃口?
    因为流应用的主流获取方式,并不是以前人们理解那种在应用市场搜索点击下载的方式。
    流应用有5种获取方式,push、wap导量、应用市场内点击、快码扫描、社交推广(这里有各种方式的视频可以看)。在这些获客方式里,传统的应用市场搜索点击的方式并不是主流量来源。
    2016年春节,DCloud为某电影票流应用厂商做push推广,发送《美人鱼》特价电影票,一次push获取了8万用户。获客效率之高是原生App推广不可比拟的。
    4月19日唯品会周年大促,也委托DCloud进行流应用push推广。因为在流应用引擎覆盖的几亿用户中,即使是一线互联网公司,其App装机占比超过20%也是寥寥无几,大量空白的用户市场需要占领挖掘。
    除了拉新,提升原有流量质量也是开发商很关心的事情。秒开、wap导量、快码等流应用发行方式能把开发商原来的低效的线上线下流量的效率提升数倍,这都是非常吸引开发商的地方。

虽然流应用好处多多,但总结这几条就够App开发商重视了。获客量大、获客成本低、获客后的运营数据指标好,大公司又不缺人,为什么不做流应用呢?
而且大公司的很多前端本身也是Hbuilder的用户,上手开发很快。

这就是大公司们纷纷做流应用的基础逻辑,很多人没想到,但说穿了也不难理解。
当然流应用不是大公司们的专属产品,创业公司一样非常需要。
创业公司的App受众面一般较窄,服务特定人群,在应用市场打广告推广是不可行的。
如何找到定向用户群,这也是流应用的重要价值。
DCloud在流应用推广中是可以定向推广的,学生、车主、球迷、女性甚至孕妇…流应用能提前根据用户画像特征更有效的对接用户和开发商的需求。

说到这儿大部分人就明白了,DCloud的变现不是通过做开发服务,而是通过发行变现。
有人还以为DCloud最近在帮各大厂商开发流应用进行收费,不是的,DCloud真的不挣开发费。
DCloud公司从成立就不是为了制作和销售App开发工具,而是为了推动HTML5的发展,重构移动互联网目前原生为主的产业生态。
左边,我们让开发者可以降低开发成本、提升获客效率;
右边,我们让手机用户省流量省空间省电,方便的获取更多优质应用服务。
DCloud不但不挣开发方面的钱,还努力给开发者免费提供比商业产品还优秀的开发工具,是希望开发者们可以制造出丰富、优质的基于HTML5的移动互联网内容。
但是不要误会发布流应用就收费,发布流应用到应用市场是免费的,只是当你计划投资推广App时,DCloud是最佳投放partner。
就像你做网站是不用给google付费的,但想推广网站就会发现google最靠谱。当然google在互联网初期并没有提供开发工具和浏览器,但这些事DCloud都做了。

08年时,人们想不到5年后的移动互联网竟然发展成这个样子。
未来也一样,HTML5重构的移动互联网生态和现在不一样,这里面有太多新机会。
对于外包商而言,他们可以做DCloud的代理,给他们的雇主提供从开发到发行的全套服务,甚至有些外包商已经给雇主免费做app但每个激活用户收取xx元。
对于工程师,流应用是一个很酷的新技能,很多大公司都需要熟悉流应用的高级开发者,值得大家花时间学习。我们有很多广告主有外包开发需求,DCloud并不接包,也可以引荐优秀的开发者接外包。

不知不觉中,各位也将见证中国发生世界级的革新。不过流应用毕竟太新,当前也还存在各种问题,希望大家一起支持流应用的发展。
大家可能还有很多疑问,欢迎到流应用QQ群交流471285299。

备注:

  1. 有开发者担心DCloud大力发展流应用会影响开发工具产品进步。
    这个不但不会,反而在众多一线互联网公司的严苛要求下,DCloud的产品体验越来越好、细节越来越完善。
  2. 有开发者不清楚DCloud的流应用上亿引擎覆盖率是怎么来的,担心自己打包成apk、ipa的变成流应用的引擎。
    不是这样的。DCloud的流应用引擎是独立的,不能内嵌在开发者的app里,其装机量和数据来源主要来自合作的应用市场。开发者打包的原生安装包并没有流应用引擎。有开发者提出想在apk里内嵌流应用引擎怎么办,后续DCloud会推出将允许开发者内嵌流应用引擎到app里的版本。
继续阅读 »

流应用是一个很多人不太容易理解的新概念,从去年大众点评外卖流应用上线时,很多人就不理解:

  1. 大众点评有原生版,为何又单独立项做流应用?成本增加了啊;
  2. 为何要做一个只能在360手助发行的版本?获取用户的潜在基数小了啊。

流应用接下来的发展就让人“更难理解”了,京东、360、有道、唯品会、携程、去哪儿、途牛、驴妈妈、神州专车、蘑菇街、当当、e代驾、卖座电影、爱鲜蜂…这些一线互联网公司怎么都在做流应用?
连做游戏的也进来了,传奇世界流应用也上线了,DCloud并没有专用游戏引擎,他们干啥呢?

其实不止是这些厂家,按目前的业务发展速度,预计年内主流的互联网App大多都会有流应用版本。

有人怀疑难道360手助强压开发商做流应用?然后由DCloud为其外包开发?
当然也不是,大家做流应用都是自愿投人投钱做,有的公司的流应用团队还不小,市场、产品、技术、运营、测试组成十几人的团队负责流应用项目。

可是流应用到底有什么魅力把这些大公司们纷纷卷进来呢?
还有,DCloud一直说面向开发者免费,工具免费、自己也不接项目开发,它怎么挣钱,它到底想干啥?
这个问题这几年一直被人问,现在也该解释了。

开发者做App,目的不是“做App”,而是给移动互联网用户提供服务。
如何获取用户、获得订单、持续复购或持续看广告?这是更根本的问题。
DCloud给开发者提供的,是一个基于HTML5的、从开发到获取用户到持续商业变现的全流程闭环生态。
并且是一个获客成本、用户质量、运营指标比原生生态更优质的新生态。
具体来讲,

  1. 获客成本低
    一个原生app的下载成本几元、激活成本十几元,新客几十元。而流应用可以把这个成本下降数倍。
  2. 获客质量不变
    流应用因为能达到原生的功能和体验,其留存、注册转换、订单转换、复购率等各项指标与原生app并无差别。DCloud为流应用开发者提供了专业的运营报表分析系统,可协助开发者优化各项业务指标。
  3. 获客数量多
    为什么流应用目前只有360手助上能搜索到,就能有足够多用户量来满足一线互联网公司的胃口?
    因为流应用的主流获取方式,并不是以前人们理解那种在应用市场搜索点击下载的方式。
    流应用有5种获取方式,push、wap导量、应用市场内点击、快码扫描、社交推广(这里有各种方式的视频可以看)。在这些获客方式里,传统的应用市场搜索点击的方式并不是主流量来源。
    2016年春节,DCloud为某电影票流应用厂商做push推广,发送《美人鱼》特价电影票,一次push获取了8万用户。获客效率之高是原生App推广不可比拟的。
    4月19日唯品会周年大促,也委托DCloud进行流应用push推广。因为在流应用引擎覆盖的几亿用户中,即使是一线互联网公司,其App装机占比超过20%也是寥寥无几,大量空白的用户市场需要占领挖掘。
    除了拉新,提升原有流量质量也是开发商很关心的事情。秒开、wap导量、快码等流应用发行方式能把开发商原来的低效的线上线下流量的效率提升数倍,这都是非常吸引开发商的地方。

虽然流应用好处多多,但总结这几条就够App开发商重视了。获客量大、获客成本低、获客后的运营数据指标好,大公司又不缺人,为什么不做流应用呢?
而且大公司的很多前端本身也是Hbuilder的用户,上手开发很快。

这就是大公司们纷纷做流应用的基础逻辑,很多人没想到,但说穿了也不难理解。
当然流应用不是大公司们的专属产品,创业公司一样非常需要。
创业公司的App受众面一般较窄,服务特定人群,在应用市场打广告推广是不可行的。
如何找到定向用户群,这也是流应用的重要价值。
DCloud在流应用推广中是可以定向推广的,学生、车主、球迷、女性甚至孕妇…流应用能提前根据用户画像特征更有效的对接用户和开发商的需求。

说到这儿大部分人就明白了,DCloud的变现不是通过做开发服务,而是通过发行变现。
有人还以为DCloud最近在帮各大厂商开发流应用进行收费,不是的,DCloud真的不挣开发费。
DCloud公司从成立就不是为了制作和销售App开发工具,而是为了推动HTML5的发展,重构移动互联网目前原生为主的产业生态。
左边,我们让开发者可以降低开发成本、提升获客效率;
右边,我们让手机用户省流量省空间省电,方便的获取更多优质应用服务。
DCloud不但不挣开发方面的钱,还努力给开发者免费提供比商业产品还优秀的开发工具,是希望开发者们可以制造出丰富、优质的基于HTML5的移动互联网内容。
但是不要误会发布流应用就收费,发布流应用到应用市场是免费的,只是当你计划投资推广App时,DCloud是最佳投放partner。
就像你做网站是不用给google付费的,但想推广网站就会发现google最靠谱。当然google在互联网初期并没有提供开发工具和浏览器,但这些事DCloud都做了。

08年时,人们想不到5年后的移动互联网竟然发展成这个样子。
未来也一样,HTML5重构的移动互联网生态和现在不一样,这里面有太多新机会。
对于外包商而言,他们可以做DCloud的代理,给他们的雇主提供从开发到发行的全套服务,甚至有些外包商已经给雇主免费做app但每个激活用户收取xx元。
对于工程师,流应用是一个很酷的新技能,很多大公司都需要熟悉流应用的高级开发者,值得大家花时间学习。我们有很多广告主有外包开发需求,DCloud并不接包,也可以引荐优秀的开发者接外包。

不知不觉中,各位也将见证中国发生世界级的革新。不过流应用毕竟太新,当前也还存在各种问题,希望大家一起支持流应用的发展。
大家可能还有很多疑问,欢迎到流应用QQ群交流471285299。

备注:

  1. 有开发者担心DCloud大力发展流应用会影响开发工具产品进步。
    这个不但不会,反而在众多一线互联网公司的严苛要求下,DCloud的产品体验越来越好、细节越来越完善。
  2. 有开发者不清楚DCloud的流应用上亿引擎覆盖率是怎么来的,担心自己打包成apk、ipa的变成流应用的引擎。
    不是这样的。DCloud的流应用引擎是独立的,不能内嵌在开发者的app里,其装机量和数据来源主要来自合作的应用市场。开发者打包的原生安装包并没有流应用引擎。有开发者提出想在apk里内嵌流应用引擎怎么办,后续DCloud会推出将允许开发者内嵌流应用引擎到app里的版本。
收起阅读 »

HBuilder中文输入法免干扰功能说明

代码助手

HBuilder7.1起支持中文符合自动替换为英文符合。
中文符号免干扰指在编写html、js、css代码时,如果处于中文输入法状态,自动将必要的符号如:;。等转为: ; .等。
如下图:
①在HTML区域输入《

②在js区域输入。


③在css 输入 》

如你不需要此功能,请在工具-选项-HBuilder-编辑器的对应html、js、css、json编辑器类型中调整
如下图:

A处开关勾选后,开启HTML文件中文免干扰功能,B处是要转义的中文字符

继续阅读 »

HBuilder7.1起支持中文符合自动替换为英文符合。
中文符号免干扰指在编写html、js、css代码时,如果处于中文输入法状态,自动将必要的符号如:;。等转为: ; .等。
如下图:
①在HTML区域输入《

②在js区域输入。


③在css 输入 》

如你不需要此功能,请在工具-选项-HBuilder-编辑器的对应html、js、css、json编辑器类型中调整
如下图:

A处开关勾选后,开启HTML文件中文免干扰功能,B处是要转义的中文字符

收起阅读 »

下拉刷新后, 如何定位到某一位置呢

下拉刷新

下拉刷新后, 如何定位到某一位置呢

下拉刷新后, 如何定位到某一位置呢

XHRHTTPREQUEST的一个坑

ajax

我使用xhrhttprequest发送POST请求,按照官网说得在调用send方法的时候传送data参数,后台死活取不到值,后面测试一看才知道传送的data参数是在作为body数据传送过去,后台接收的post参数为空,raw参数才是我们传送的值
后来改为mui.ajax就没问题了.....
特记录在这里,免得大家入坑

继续阅读 »

我使用xhrhttprequest发送POST请求,按照官网说得在调用send方法的时候传送data参数,后台死活取不到值,后面测试一看才知道传送的data参数是在作为body数据传送过去,后台接收的post参数为空,raw参数才是我们传送的值
后来改为mui.ajax就没问题了.....
特记录在这里,免得大家入坑

收起阅读 »