HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

解决:最近升级后安卓手机无法自动更新的问题

最近升级了HBuilder版本,一直用的好好的自动在线升级的功能,在苹果手机上使用正常,但是在安卓手机上提示:找不到文件路径;

经过反复调试,后来终于发现并解决问题。

原来关键代码:plus.downloader.createDownload( wgtUrl, {filename:"temp/update/"}, function(d,status){

修改后代码 :plus.downloader.createDownload( wgtUrl, {filename:"_doc/update/"}, function(d,status){

修改代码后自动在线升级功能恢复正常。

经过反复实验,发现在安卓手机上,"_doc/update/" 这个文件路径不能够自定义,只有改成这个路径才能恢复正常。

继续阅读 »

最近升级了HBuilder版本,一直用的好好的自动在线升级的功能,在苹果手机上使用正常,但是在安卓手机上提示:找不到文件路径;

经过反复调试,后来终于发现并解决问题。

原来关键代码:plus.downloader.createDownload( wgtUrl, {filename:"temp/update/"}, function(d,status){

修改后代码 :plus.downloader.createDownload( wgtUrl, {filename:"_doc/update/"}, function(d,status){

修改代码后自动在线升级功能恢复正常。

经过反复实验,发现在安卓手机上,"_doc/update/" 这个文件路径不能够自定义,只有改成这个路径才能恢复正常。

收起阅读 »

【分享】静默更新

/*  
* 静默更新插件  
* 直接appUpadata.init()去调用此插件  
 */  
! function(window, undefined) {  
    var appUpdata = window.appUpdata = {  
        init: function() {  
            var that = this;  
            if(plus) {  
                plus.runtime.getProperty(plus.runtime.appid, function(inf) {  
                    var wgtVer = inf.version;  
                    bpAjax("此处为利用ajax请求服务器的静默更新版本,后台返回一个下载地址", {  
                        version: plus.runtime.version,  
                        resVersion: wgtVer  
                    }, function(d) {  
                        that.downFn(d.data.url);  
                    }, function(d) {  
                        //mui.toast(d.info)  
                    }, 1, "版本")  
                });  

            }  
        },  
        // 下载文件  
        downFn: function(wgtUrl) {  
            var that = this;  
            if(plus) {  
                plus.downloader.createDownload(wgtUrl, {  
                    filename: "_doc/update/"  
                }, function(d, status) {  
                    if(status == 200) {  
                        that.installWgt(d.filename);  
                    } else {  
                        console.log("下载版本失败!");  
                    }  
                }).start();  
            }  
        },  
        // 安装文件  
        installWgt: function(path) {  
            if(plus) {  
                plus.runtime.install(path, {}, function() {  
                    console.log("安装版本成功!");  
                }, function(e) {  
                    console.log("安装版本失败[" + e.code + "]:" + e.message);  
                });  
            }  
        }  
    }  
}(window)
继续阅读 »
/*  
* 静默更新插件  
* 直接appUpadata.init()去调用此插件  
 */  
! function(window, undefined) {  
    var appUpdata = window.appUpdata = {  
        init: function() {  
            var that = this;  
            if(plus) {  
                plus.runtime.getProperty(plus.runtime.appid, function(inf) {  
                    var wgtVer = inf.version;  
                    bpAjax("此处为利用ajax请求服务器的静默更新版本,后台返回一个下载地址", {  
                        version: plus.runtime.version,  
                        resVersion: wgtVer  
                    }, function(d) {  
                        that.downFn(d.data.url);  
                    }, function(d) {  
                        //mui.toast(d.info)  
                    }, 1, "版本")  
                });  

            }  
        },  
        // 下载文件  
        downFn: function(wgtUrl) {  
            var that = this;  
            if(plus) {  
                plus.downloader.createDownload(wgtUrl, {  
                    filename: "_doc/update/"  
                }, function(d, status) {  
                    if(status == 200) {  
                        that.installWgt(d.filename);  
                    } else {  
                        console.log("下载版本失败!");  
                    }  
                }).start();  
            }  
        },  
        // 安装文件  
        installWgt: function(path) {  
            if(plus) {  
                plus.runtime.install(path, {}, function() {  
                    console.log("安装版本成功!");  
                }, function(e) {  
                    console.log("安装版本失败[" + e.code + "]:" + e.message);  
                });  
            }  
        }  
    }  
}(window)
收起阅读 »

关于mui的两个上拉加载下拉刷新遇到的几个问题

第一种方式,无需插件,但是页面不能通过url传参,会起冲突。
冲突效果:页面不能滑动,且在日志里报错。如图所示
代码结构
解决的方式
1、可以将传参的内容通过mui.openwindow()跳转页面传参
2、可以用localStorage进行存储,跳转后取出使用后并再销毁
html
<div id="pullrefresh" class="mui-content mui-scroll-wrapper" >
<div class="mui-scroll">

            <ul class="mui-table-view">   

            </ul>                                                                                                               
        </div>  
    </div>  

js
mui.init({
pullRefresh: {
container: '#pullrefresh' ,
up: {
contentrefresh : "正在加载中...",
callback: ajax_allAddress //自定义加载方法
}
}
});
第二种方式,需要mui的上拉下拉组件,但是那中刷新方式会激活mui.back返回上一页的刷新页面代码
冲突效果:滑动时会导致refresh的自定义代码运行导致页面闪烁
上拉下拉组件
<script src="../js/mui.pullToRefresh.js"></script>
<script src="../js/mui.pullToRefresh.material.js"></script>
监听父页面js
mui.init({
beforeback: function() {
     //获得父页面的webview
var list = plus.webview.currentWebview().opener(); //返回的页面
     //触发父页面的自定义事件(refresh),从而进行刷新
mui.fire(list, 'refresh');
//返回true,继续页面关闭逻辑
return true;
}
});
父页面刷新js
//监听页面刷新
window.addEventListener("refresh",function(e){
function1();//自定义部分
});
父页面上拉加载html结构
<div class="mui-content">
<div id="slider" class="mui-slider mui-fullscreen">
<div id="sliderSegmentedControl" class="mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<div id="my_order_top" class="mui-scroll">
<a class="mui-control-item mui-active" href="#item1mobile" data-value="1">
已保存
</a>
<a class="mui-control-item" href="#item2mobile" data-value="2">
已提交
</a>
<a class="mui-control-item" href="#item3mobile" data-value="3">
已完成
</a>
</div>
</div>
<div class="mui-slider-group">
<div id="item1mobile" class="mui-slider-item mui-control-content mui-active">
<div class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="orderSheet_list" id="orderSheet_list1">

                            </ul>  
                        </div>  
                    </div>  
                </div>  
                <div id="item2mobile" class="mui-slider-item mui-control-content">  
                    <div class="mui-scroll-wrapper">  
                        <div class="mui-scroll">  
                            <ul class="orderSheet_list" id="orderSheet_list2">  
                            </ul>  
                        </div>  
                    </div>  
                </div>  
                <div id="item3mobile" class="mui-slider-item mui-control-content">  
                    <div class="mui-scroll-wrapper">  
                        <div class="mui-scroll">  
                            <ul class="orderSheet_list" id="orderSheet_list3">  
                            </ul>  
                        </div>  
                    </div>  
                </div>          
            </div>  
        </div>  
    </div>  

父页面上拉加载js结构
//阻尼系数
var deceleration = mui.os.ios?0.003:0.0009;
mui('.mui-scroll-wrapper').scroll({
bounce: false,
indicators: true, //是否显示滚动条
deceleration:deceleration
});
//循环初始化所有下拉刷新,上拉加载。
mui.each(document.querySelectorAll('.mui-slider-group .mui-scroll'), function(index, pullRefreshEl) {
mui(pullRefreshEl).pullToRefresh({
up: {
callback: function() {
var self = this;
setTimeout(function() {
self.endPullUpToRefresh();
}, 1000);
}
}
});
});
解决的方式
1、不使用refresh监听事件
2、选用第一种刷新方式
3、修改组件源码

继续阅读 »

第一种方式,无需插件,但是页面不能通过url传参,会起冲突。
冲突效果:页面不能滑动,且在日志里报错。如图所示
代码结构
解决的方式
1、可以将传参的内容通过mui.openwindow()跳转页面传参
2、可以用localStorage进行存储,跳转后取出使用后并再销毁
html
<div id="pullrefresh" class="mui-content mui-scroll-wrapper" >
<div class="mui-scroll">

            <ul class="mui-table-view">   

            </ul>                                                                                                               
        </div>  
    </div>  

js
mui.init({
pullRefresh: {
container: '#pullrefresh' ,
up: {
contentrefresh : "正在加载中...",
callback: ajax_allAddress //自定义加载方法
}
}
});
第二种方式,需要mui的上拉下拉组件,但是那中刷新方式会激活mui.back返回上一页的刷新页面代码
冲突效果:滑动时会导致refresh的自定义代码运行导致页面闪烁
上拉下拉组件
<script src="../js/mui.pullToRefresh.js"></script>
<script src="../js/mui.pullToRefresh.material.js"></script>
监听父页面js
mui.init({
beforeback: function() {
     //获得父页面的webview
var list = plus.webview.currentWebview().opener(); //返回的页面
     //触发父页面的自定义事件(refresh),从而进行刷新
mui.fire(list, 'refresh');
//返回true,继续页面关闭逻辑
return true;
}
});
父页面刷新js
//监听页面刷新
window.addEventListener("refresh",function(e){
function1();//自定义部分
});
父页面上拉加载html结构
<div class="mui-content">
<div id="slider" class="mui-slider mui-fullscreen">
<div id="sliderSegmentedControl" class="mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<div id="my_order_top" class="mui-scroll">
<a class="mui-control-item mui-active" href="#item1mobile" data-value="1">
已保存
</a>
<a class="mui-control-item" href="#item2mobile" data-value="2">
已提交
</a>
<a class="mui-control-item" href="#item3mobile" data-value="3">
已完成
</a>
</div>
</div>
<div class="mui-slider-group">
<div id="item1mobile" class="mui-slider-item mui-control-content mui-active">
<div class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="orderSheet_list" id="orderSheet_list1">

                            </ul>  
                        </div>  
                    </div>  
                </div>  
                <div id="item2mobile" class="mui-slider-item mui-control-content">  
                    <div class="mui-scroll-wrapper">  
                        <div class="mui-scroll">  
                            <ul class="orderSheet_list" id="orderSheet_list2">  
                            </ul>  
                        </div>  
                    </div>  
                </div>  
                <div id="item3mobile" class="mui-slider-item mui-control-content">  
                    <div class="mui-scroll-wrapper">  
                        <div class="mui-scroll">  
                            <ul class="orderSheet_list" id="orderSheet_list3">  
                            </ul>  
                        </div>  
                    </div>  
                </div>          
            </div>  
        </div>  
    </div>  

父页面上拉加载js结构
//阻尼系数
var deceleration = mui.os.ios?0.003:0.0009;
mui('.mui-scroll-wrapper').scroll({
bounce: false,
indicators: true, //是否显示滚动条
deceleration:deceleration
});
//循环初始化所有下拉刷新,上拉加载。
mui.each(document.querySelectorAll('.mui-slider-group .mui-scroll'), function(index, pullRefreshEl) {
mui(pullRefreshEl).pullToRefresh({
up: {
callback: function() {
var self = this;
setTimeout(function() {
self.endPullUpToRefresh();
}, 1000);
}
}
});
});
解决的方式
1、不使用refresh监听事件
2、选用第一种刷新方式
3、修改组件源码

收起阅读 »

利用叮铛制做一个app的原理逻辑

小程序 移动APP

听起来有点理想主义,更甚至有点荒唐?没错,零代码开发正是一种理想的应用生产方式,我们回顾一下应用开发的历史就会发现,开发一个应用,需要写的代码越来越少,到最理想的状态就是不需要写代码。

叮铛应用(www.ddapp.com),是这条道路上唯一一个执着且坚定的实践者,并通过大量的实例反复验证了这条道路的可行性。这一点都不荒唐,而是历史的趋势。叮铛应用是一款集iOS、安卓Android、小程序、H5四端于一体的零代码移动应用生产运营平台,为全行业多领域提供应用解决方案—电商、区域社区、知识付费,本地社群,量身定制服务,高效制作纯原生代码封装的移动app应用

一、应用开发的发展路径
首先回顾一下应用开发的发展历史,我们会发现应用开发的代码越来越少的规律。

刀耕火种期
这个时期,应用开发生态刚萌牙,应用的每一个功能,从服务端到客户端都要开发者一行一行代码的敲,如果需要用到服务器,通常也是开发者购买物理主机,托管到电信机房里去,装机维护全都需要自己搞定。

模块复用期
随着代码的积累,有重用意识的开发者开始把通用的功能剥离出来,形成为一个个独立的功能模块。他们还通过内部共享或开源的方式,让越来越多人基于此可以快速实现一个功能。

云服务期
云计算的兴旺发达,让应用开发有了质的改变。

一是表现在机器的托管上,开发者慢慢的从购买主机,租用机购托管服务器,变成了直接购买IAAS服务商的云主机。
二是应用的快速开发上。
PAAS(平台即服务)的百花绽放,让开发者几行代码就可以实现推送、分享、文件存储甚至部署等原本繁琐、复杂的功能,而且不需要额外的维护成本。开发者只需要关注核心业务,因此代码也更少了。
BAAS(后端即服务)的出现,一下子解放了后端程序员,这下应用开发者只需要有客户端或前端开发者就够,开发成本一下子又砍掉一大半;要写的代码也只剩下客户端与前端了。

AAAS
AAAS(应用即服务,不同于SAAS)是叮铛应用提出的一个新名词,在BAAS的解放后端程序员的基础上,AAAS顺手把客户端和前端程序员也解放了。到此,真正达到零代码应用开发。

二、叮铛应用是怎么做到的
简单来说,叮铛把应用服务端和客户端的技术进行了高度的抽象,让组成应用的零件都变得通用且具备高度可配置性。可以这么说,我们通过叮铛把一个应用配置出来。

下面我们通过解构一个手机app应用,来建立起叮铛应用的世界观。

一个app的构成
一个手机app主要由两大部分的程序运行支撑起来的:客户端和服务端。

客户端,运行在用户的手机上,即用户直接使用到的app,例如微信、微博app,客户端由各种各样的功能界面组合而成,用于展示应用的数据并和用户产生交互。
服务端,运行在云端的某一台服务器上,通过网络与客户端连接起来,用于保存应用和用户的数据。

服务端
先讲服务端,因为服务端是存储应用业务数据的地方,而业务数据是一个应用的核心灵魂。我们要开发一个应用,通常要先梳理出业务数据,其次才是考虑如何设计它的界面和交互。

服务端有两个重要的角色:数据表与触发器。

数据表,用于存储应用的业务数据,表达业务数据之间的逻辑关系。
触发器,用户行为触发服务端执行其他任务的调度机制。
两者紧密结合,可以完成服务端的大部分需求场景。

下面分别认识一下。

  1. 数据表
    上面讲过,服务端的主要职责是存储应用的业务数据,数据表正是用于实现此目的的。

没学过数据库或没有开发经验的同学可能会担心自己不能理解数据表的概念,在此,我用一个大家常见的场景来类比一下,大家就会明白了。

大家都使用过Excel这个表格软件,下面用Excel来做一张班级的学生花名册的表格。

第一步:设计表结构
首先,我们要确定一下,这张表格要记录学生的什么资料,如:姓名、性别、籍贯、民族、学号、手机号码、生日等,确定完毕后,我们先创建一行表头,用于表示这个表格每一列表示学生的哪种信息,如下图:

表头创建完之后,我们算是设计好了学生资料的结构——一个学生的资料,由姓名、性别等信息(或称为列)构成。

第二步:填充表
接下来,我们向设计好的表格里面填数据,连续填进去多条学生的数据。

在叮铛,一张数据表就像一张Excel表类似,你要先设计好表结构,才能去填数据,让用户在客户端访问它们。

在叮铛,我们把表格中的每一列叫做字段,即叮铛的数据表结构是由多个字段组成的。如上面示例中的学生表的结构,由姓名、性别等多个字段组成。每个字段都有它对应的数据类型,如姓名是文本、手机号码是数字、生日是日期等,和Excel里单元格的格式是同样的道理。

数据表定义好,数据也准备好了,用户怎么通过客户端访问呢?在客户端一节中将有详细说明。
更多关于数据表的内容请参考【数据表】一节。

  1. 触发器
    请想象以下的场景:
    当一个客户在app下了一个订单,想要给商家推送一条消息。
    当一篇文章被点赞超过200次时,将该文章设置为热门文章。
    在叮铛,这些场景都需要通过触发器来实现。

触发器,顾名思义,发生了某件事情后,触发另一件事情的发生。所以,一个触发器是由【触发事件】和【响应动作】两个环节构成,当A事件发生时,触发B动向响应。

触发事件
叮铛内置了一系列的事件,供用户选择使用,例如:用户登录、用户购买商品成功、数据表发生改表等。用户选择某一种关心的事件后,需要设定其触发条件,当触发条件成立,叮铛会去执行相应的响应动作。

响应动作
叮铛同样内置了一系列的响应动作,供用户选择使用,例如:推送消息、添加用户到某个分组、修改数据、发送邮件等等。用户选择需要响应的动作后,设置对应的参数即可。创建一个触发器时,可以添加多个响应动作,所有响应动作都会被放进执行队列中异步执行。

以上面说的场景1为例,添加一个触发器:
触发事件,选择用户购买成功事件,不修改配置的情况默认用户购买所有商品都会触发该事件,如果你只关注其中某一种商品,那配置一下过滤条件即可。
响应动作,选择推送消息,消息接收人填上商家的用户标识,内容中填写“你有一条新订单”。
保存即完成想要的功能,当有人在你的app下单时,你(商家)的app会收到一条推送消息。

未来,随着业务能力的丰富,叮铛会添加更多触发事件及响应动作,满足用户的不同需求。
更多触发器的内容请参考【触发器】一节。

客户端
叮铛对客户端程序进行了解构,重组,抽象出一套通用的界面构建规则,满足大部份app的数据展示和交互需求。
app由多个页面组成。
一个页面由多个组件构成。
布局组件(允许自定义)由多个控件构成。

由此可见,客户端界面,有三种主要的组成元素:页面、组件、控件。

  1. 页面
    app是由多个页面组成的,在叮铛,我们把页面划分为四个类型:
    通用页
    详情页
    组合页
    功能页

通用页
能直接使用,无须额外提供数据即可使用的页面,通常一个app的顶级页面,都是此类页面,实例如首页、推荐图书列表等。

详情页
与通用页相比,详情页需要指定一种数据类型,代表该详情页用于展示该类型数据内容的。此类页面为展示某条数据和该数据相关联的其他数据用的,脱离指定的数据无法直接使用,通常用于点击某条数据后打开的页面,不会用于app的顶级页面。实例如图书内容展示和相关评论页面。

组合页
顾名思义,由多个通用页或多个详情页组合起来的页面集,叫组合页。组合页的组合规则是:
一个组合页里的页面要么全是通用页,要么全是详情页。
如果组合页里的页面是详情页,这些详情页的指定数据必须是相同的。

功能页
这类页面不需要用户制作,是由叮铛开发好,提供给用户直接使用的。

  1. 组件
    组件是构成页面的基本单元,拿到一个页面的设计图后,我们会把页面分拆成多个组件,在叮铛上创建每个组件,拼成一个完整页面。

叮铛提供了丰定的组件类型,每种类型又提供了大量的模板,让应用界面的搭建变得轻松。

常见的组件为列表组件(又细分多种风格的列表)、栏目栏、幻灯、导航器、布局组件,每一个组件都有自己完整的界面显示、数据读取方法和与用户的交互方式,使用者可以通过修改组件的相关属性,达到自定义其外观、数据源、交互方式的目的。

设计组件
叮铛用户可以通过设置组件开放出来的属性来达到定制组件样式的目的。叮铛的组件抽象度很高,一个组件通过不同的属性组合呈现出来的样式千变万化。
在页面的管理后台,选择一个页面,点击设计组件可以看到该组件所有开放的属性。修改它们,通过【叮铛应用助手】这个app可以实时看到页面的效果。

数据
组件需要显示数据,但有两个问题需要解决:
组件需要显示什么数据?
怎么显示这些数据?

解决第一个问题的方法,是给组件设定一个数据源,告诉组件要显示哪个数据表的数据。当我们需要有选择性地显示数据表的数据时,可以对数据源设定一些筛选条件。

在制作后台 -> 页面管理 -> 组件管理 页面中,选定一个组件,多数组件会有数据来源设定的选项。

组件设定了数据源属性,在应用运行的时候会到服务器去获取相关的数据。

第二个问题,给组件指定了数据来源,数据有了,该如何显示?答案是建立数据表字段与组件内控件的绑定关系。

组件由更小的控件组成,组件内的每一个控件,都承担着展示某个字段信息展现和交互的责任。

在制作后台 -> 页面管理 -> 组件管理页面中,选定一个组件,都会有一个显示内容设定选项,用于设置控件(显示字段)与数据表字段(内容)字段之前的关系。

设置控件与数据表字段的绑定关系的同时,我们还可以进一步对显示的格式进行设置,在客户端内置的【客户端函数】帮助下达到各种格式化的目的。

行为管理
用户在组件上的一个点击,会引发客户端多种多样的响应,例如跳转到另一个页面、拨打一个电话号码等。在叮铛,这些行为可以让我们自由配置。
在制作后台 -> 页面管理 -> 组件管理页面中,选定一个组件,都会有一个点击事件的选项,用于设置组件里某个部位被点击,所以做出的响应。

  1. 控件
    控件是组件的组成单元。
    叮铛很多组件的结构都是固定的,允许你去修改它们的样式,给里面的控件绑定显示的数据表字段和响应的事件,但无法修改其内部结构,例如要给组件增加一个按钮控件、修改组件内元素的排列等。
    为了满足应用界面多样化的需求,叮铛提供了布局组件(DIY组件),允许用户使用控件任意设计出组件的内容和样式。
    布局组件在叮铛内部广泛使用于其他列表组件的扩展区域。
    控件是叮铛界面体系里,组成界面的最细粒度的元素,通常表现为一段文字,一个按钮,一张图片,一段视频等。布局组件是一块画布,你可以在上面任意摆放各种控件,设计出你需要的界面。

  2. 界面与数据
    客户端还承担起数据展示的作用,那么数据又是如何与界面的元素结合到一起的呢?上一节介绍组件时,说了组件数据来源和展示方式。本节再详细讲一讲数据在客户端的组织和使用。

应用的业务数据一开始都存储在服务器端,当应用在手机上被打开时,叮铛会根据所显示的页面及其包含组件所配置的数据源,从服务器上把数据取下来,再按数据字段与控件绑定的关系显示出来。

在客户端,数据按有效范围被分为四种:

app全局数据。指在整个app范围内均可被使用的数据,如用户数据、app基本信息、地理位置等。目前仅有固定几种数据,稍晚会开放给用户自己定义app的全局数据。
页面数据(详情页的指定数据)。该数据只存在于详情页,可用范围是整个详情页。页面内所有组件均可使用该数据。
组件数据(当前数据)。即组件所配置的数据源,这些数据只能被所属的组件使用。
页面参数。数据可以在页面之间传递,传递方法,就是通过页面参数的方式实现,参数的有效范围是接受参数的整个页面。(关于页面参数更多内容,见【页面参数】一节)

所以,你在制作后台会经常看到弹出的数据选择器当中,有上面几组数据供你选择。

  1. URI
    叮铛应用的每个页面都有自己的URI。叮铛通过URI打开页面,调用系统的功能。
    URI除了用于打开页面,还广泛用于调用一些特殊的操作,例如打电话、发短信。叮铛为大家提供了较为丰富的URI,可以满足多数场景的需求,未来还会持续增加。
    给有开发经验的小伙伴另一种视角:把URI当作客户端内置函数的一种调用方式。

内置功能集
叮铛提供了许多通用的功能,让大家开箱即用,例如会员系统、权限系统、注册、登录、评论、支付、推送等。这些功能在各个应用中的表现大同小异,因此,叮铛把它们做成固化的功能,方便开发者使用。

叮铛提供的通用功能均保留有一定的可扩展能力,让大家根据实际需求来做更个性化的调整,例如:会员字段允许增加自定义字段、任何数据都可以摇身一变变成商品等等。

部份内置功能默认开启,其余功能需要在叮铛应用制作后台的功能菜单中打开。更详尽的功能介绍与使用方式,见【内置功能】一节。

三、叮铛应用的二次开发

零代码开发是叮铛的终极目标,但现阶段仍然会有一些需求在叮铛上是暂时做不出来,为解决这个问题,叮铛成立了专门的开放平台组。

如果叮铛提供的能力仍然不能满足需要,如果你恰好具备一定的开发能力,叮铛应用开发平台能让二次开发。开放平台提供以下几种二次开发的途径:

H5接入,叮铛提供了JSSDK,部分在叮铛应用暂不能实现的app页面,可使用H5来开发,嵌入到制作的app中。
双向SDK:a.叮铛提供插件开发套件,让开发者开发符合叮铛标准的原生插件,上传到开发者自己的插件库,与制作的app进行打包。b.叮铛还提供把制作好的app页面导出为SDK,被开发者整合进他们原有的自主研发的app当中
第三方数据的引入。如果开发者有自己的业务服务器,可以使用叮铛的数据引入机制,既能让你的数据保存在自己的服务器上,又能让你享受叮铛制作app的便利。
生成可交付的代码。遇到需要交付代码的客户?我们可以搞定,叮铛可以为你生成具备交付能力的代码。

继续阅读 »

听起来有点理想主义,更甚至有点荒唐?没错,零代码开发正是一种理想的应用生产方式,我们回顾一下应用开发的历史就会发现,开发一个应用,需要写的代码越来越少,到最理想的状态就是不需要写代码。

叮铛应用(www.ddapp.com),是这条道路上唯一一个执着且坚定的实践者,并通过大量的实例反复验证了这条道路的可行性。这一点都不荒唐,而是历史的趋势。叮铛应用是一款集iOS、安卓Android、小程序、H5四端于一体的零代码移动应用生产运营平台,为全行业多领域提供应用解决方案—电商、区域社区、知识付费,本地社群,量身定制服务,高效制作纯原生代码封装的移动app应用

一、应用开发的发展路径
首先回顾一下应用开发的发展历史,我们会发现应用开发的代码越来越少的规律。

刀耕火种期
这个时期,应用开发生态刚萌牙,应用的每一个功能,从服务端到客户端都要开发者一行一行代码的敲,如果需要用到服务器,通常也是开发者购买物理主机,托管到电信机房里去,装机维护全都需要自己搞定。

模块复用期
随着代码的积累,有重用意识的开发者开始把通用的功能剥离出来,形成为一个个独立的功能模块。他们还通过内部共享或开源的方式,让越来越多人基于此可以快速实现一个功能。

云服务期
云计算的兴旺发达,让应用开发有了质的改变。

一是表现在机器的托管上,开发者慢慢的从购买主机,租用机购托管服务器,变成了直接购买IAAS服务商的云主机。
二是应用的快速开发上。
PAAS(平台即服务)的百花绽放,让开发者几行代码就可以实现推送、分享、文件存储甚至部署等原本繁琐、复杂的功能,而且不需要额外的维护成本。开发者只需要关注核心业务,因此代码也更少了。
BAAS(后端即服务)的出现,一下子解放了后端程序员,这下应用开发者只需要有客户端或前端开发者就够,开发成本一下子又砍掉一大半;要写的代码也只剩下客户端与前端了。

AAAS
AAAS(应用即服务,不同于SAAS)是叮铛应用提出的一个新名词,在BAAS的解放后端程序员的基础上,AAAS顺手把客户端和前端程序员也解放了。到此,真正达到零代码应用开发。

二、叮铛应用是怎么做到的
简单来说,叮铛把应用服务端和客户端的技术进行了高度的抽象,让组成应用的零件都变得通用且具备高度可配置性。可以这么说,我们通过叮铛把一个应用配置出来。

下面我们通过解构一个手机app应用,来建立起叮铛应用的世界观。

一个app的构成
一个手机app主要由两大部分的程序运行支撑起来的:客户端和服务端。

客户端,运行在用户的手机上,即用户直接使用到的app,例如微信、微博app,客户端由各种各样的功能界面组合而成,用于展示应用的数据并和用户产生交互。
服务端,运行在云端的某一台服务器上,通过网络与客户端连接起来,用于保存应用和用户的数据。

服务端
先讲服务端,因为服务端是存储应用业务数据的地方,而业务数据是一个应用的核心灵魂。我们要开发一个应用,通常要先梳理出业务数据,其次才是考虑如何设计它的界面和交互。

服务端有两个重要的角色:数据表与触发器。

数据表,用于存储应用的业务数据,表达业务数据之间的逻辑关系。
触发器,用户行为触发服务端执行其他任务的调度机制。
两者紧密结合,可以完成服务端的大部分需求场景。

下面分别认识一下。

  1. 数据表
    上面讲过,服务端的主要职责是存储应用的业务数据,数据表正是用于实现此目的的。

没学过数据库或没有开发经验的同学可能会担心自己不能理解数据表的概念,在此,我用一个大家常见的场景来类比一下,大家就会明白了。

大家都使用过Excel这个表格软件,下面用Excel来做一张班级的学生花名册的表格。

第一步:设计表结构
首先,我们要确定一下,这张表格要记录学生的什么资料,如:姓名、性别、籍贯、民族、学号、手机号码、生日等,确定完毕后,我们先创建一行表头,用于表示这个表格每一列表示学生的哪种信息,如下图:

表头创建完之后,我们算是设计好了学生资料的结构——一个学生的资料,由姓名、性别等信息(或称为列)构成。

第二步:填充表
接下来,我们向设计好的表格里面填数据,连续填进去多条学生的数据。

在叮铛,一张数据表就像一张Excel表类似,你要先设计好表结构,才能去填数据,让用户在客户端访问它们。

在叮铛,我们把表格中的每一列叫做字段,即叮铛的数据表结构是由多个字段组成的。如上面示例中的学生表的结构,由姓名、性别等多个字段组成。每个字段都有它对应的数据类型,如姓名是文本、手机号码是数字、生日是日期等,和Excel里单元格的格式是同样的道理。

数据表定义好,数据也准备好了,用户怎么通过客户端访问呢?在客户端一节中将有详细说明。
更多关于数据表的内容请参考【数据表】一节。

  1. 触发器
    请想象以下的场景:
    当一个客户在app下了一个订单,想要给商家推送一条消息。
    当一篇文章被点赞超过200次时,将该文章设置为热门文章。
    在叮铛,这些场景都需要通过触发器来实现。

触发器,顾名思义,发生了某件事情后,触发另一件事情的发生。所以,一个触发器是由【触发事件】和【响应动作】两个环节构成,当A事件发生时,触发B动向响应。

触发事件
叮铛内置了一系列的事件,供用户选择使用,例如:用户登录、用户购买商品成功、数据表发生改表等。用户选择某一种关心的事件后,需要设定其触发条件,当触发条件成立,叮铛会去执行相应的响应动作。

响应动作
叮铛同样内置了一系列的响应动作,供用户选择使用,例如:推送消息、添加用户到某个分组、修改数据、发送邮件等等。用户选择需要响应的动作后,设置对应的参数即可。创建一个触发器时,可以添加多个响应动作,所有响应动作都会被放进执行队列中异步执行。

以上面说的场景1为例,添加一个触发器:
触发事件,选择用户购买成功事件,不修改配置的情况默认用户购买所有商品都会触发该事件,如果你只关注其中某一种商品,那配置一下过滤条件即可。
响应动作,选择推送消息,消息接收人填上商家的用户标识,内容中填写“你有一条新订单”。
保存即完成想要的功能,当有人在你的app下单时,你(商家)的app会收到一条推送消息。

未来,随着业务能力的丰富,叮铛会添加更多触发事件及响应动作,满足用户的不同需求。
更多触发器的内容请参考【触发器】一节。

客户端
叮铛对客户端程序进行了解构,重组,抽象出一套通用的界面构建规则,满足大部份app的数据展示和交互需求。
app由多个页面组成。
一个页面由多个组件构成。
布局组件(允许自定义)由多个控件构成。

由此可见,客户端界面,有三种主要的组成元素:页面、组件、控件。

  1. 页面
    app是由多个页面组成的,在叮铛,我们把页面划分为四个类型:
    通用页
    详情页
    组合页
    功能页

通用页
能直接使用,无须额外提供数据即可使用的页面,通常一个app的顶级页面,都是此类页面,实例如首页、推荐图书列表等。

详情页
与通用页相比,详情页需要指定一种数据类型,代表该详情页用于展示该类型数据内容的。此类页面为展示某条数据和该数据相关联的其他数据用的,脱离指定的数据无法直接使用,通常用于点击某条数据后打开的页面,不会用于app的顶级页面。实例如图书内容展示和相关评论页面。

组合页
顾名思义,由多个通用页或多个详情页组合起来的页面集,叫组合页。组合页的组合规则是:
一个组合页里的页面要么全是通用页,要么全是详情页。
如果组合页里的页面是详情页,这些详情页的指定数据必须是相同的。

功能页
这类页面不需要用户制作,是由叮铛开发好,提供给用户直接使用的。

  1. 组件
    组件是构成页面的基本单元,拿到一个页面的设计图后,我们会把页面分拆成多个组件,在叮铛上创建每个组件,拼成一个完整页面。

叮铛提供了丰定的组件类型,每种类型又提供了大量的模板,让应用界面的搭建变得轻松。

常见的组件为列表组件(又细分多种风格的列表)、栏目栏、幻灯、导航器、布局组件,每一个组件都有自己完整的界面显示、数据读取方法和与用户的交互方式,使用者可以通过修改组件的相关属性,达到自定义其外观、数据源、交互方式的目的。

设计组件
叮铛用户可以通过设置组件开放出来的属性来达到定制组件样式的目的。叮铛的组件抽象度很高,一个组件通过不同的属性组合呈现出来的样式千变万化。
在页面的管理后台,选择一个页面,点击设计组件可以看到该组件所有开放的属性。修改它们,通过【叮铛应用助手】这个app可以实时看到页面的效果。

数据
组件需要显示数据,但有两个问题需要解决:
组件需要显示什么数据?
怎么显示这些数据?

解决第一个问题的方法,是给组件设定一个数据源,告诉组件要显示哪个数据表的数据。当我们需要有选择性地显示数据表的数据时,可以对数据源设定一些筛选条件。

在制作后台 -> 页面管理 -> 组件管理 页面中,选定一个组件,多数组件会有数据来源设定的选项。

组件设定了数据源属性,在应用运行的时候会到服务器去获取相关的数据。

第二个问题,给组件指定了数据来源,数据有了,该如何显示?答案是建立数据表字段与组件内控件的绑定关系。

组件由更小的控件组成,组件内的每一个控件,都承担着展示某个字段信息展现和交互的责任。

在制作后台 -> 页面管理 -> 组件管理页面中,选定一个组件,都会有一个显示内容设定选项,用于设置控件(显示字段)与数据表字段(内容)字段之前的关系。

设置控件与数据表字段的绑定关系的同时,我们还可以进一步对显示的格式进行设置,在客户端内置的【客户端函数】帮助下达到各种格式化的目的。

行为管理
用户在组件上的一个点击,会引发客户端多种多样的响应,例如跳转到另一个页面、拨打一个电话号码等。在叮铛,这些行为可以让我们自由配置。
在制作后台 -> 页面管理 -> 组件管理页面中,选定一个组件,都会有一个点击事件的选项,用于设置组件里某个部位被点击,所以做出的响应。

  1. 控件
    控件是组件的组成单元。
    叮铛很多组件的结构都是固定的,允许你去修改它们的样式,给里面的控件绑定显示的数据表字段和响应的事件,但无法修改其内部结构,例如要给组件增加一个按钮控件、修改组件内元素的排列等。
    为了满足应用界面多样化的需求,叮铛提供了布局组件(DIY组件),允许用户使用控件任意设计出组件的内容和样式。
    布局组件在叮铛内部广泛使用于其他列表组件的扩展区域。
    控件是叮铛界面体系里,组成界面的最细粒度的元素,通常表现为一段文字,一个按钮,一张图片,一段视频等。布局组件是一块画布,你可以在上面任意摆放各种控件,设计出你需要的界面。

  2. 界面与数据
    客户端还承担起数据展示的作用,那么数据又是如何与界面的元素结合到一起的呢?上一节介绍组件时,说了组件数据来源和展示方式。本节再详细讲一讲数据在客户端的组织和使用。

应用的业务数据一开始都存储在服务器端,当应用在手机上被打开时,叮铛会根据所显示的页面及其包含组件所配置的数据源,从服务器上把数据取下来,再按数据字段与控件绑定的关系显示出来。

在客户端,数据按有效范围被分为四种:

app全局数据。指在整个app范围内均可被使用的数据,如用户数据、app基本信息、地理位置等。目前仅有固定几种数据,稍晚会开放给用户自己定义app的全局数据。
页面数据(详情页的指定数据)。该数据只存在于详情页,可用范围是整个详情页。页面内所有组件均可使用该数据。
组件数据(当前数据)。即组件所配置的数据源,这些数据只能被所属的组件使用。
页面参数。数据可以在页面之间传递,传递方法,就是通过页面参数的方式实现,参数的有效范围是接受参数的整个页面。(关于页面参数更多内容,见【页面参数】一节)

所以,你在制作后台会经常看到弹出的数据选择器当中,有上面几组数据供你选择。

  1. URI
    叮铛应用的每个页面都有自己的URI。叮铛通过URI打开页面,调用系统的功能。
    URI除了用于打开页面,还广泛用于调用一些特殊的操作,例如打电话、发短信。叮铛为大家提供了较为丰富的URI,可以满足多数场景的需求,未来还会持续增加。
    给有开发经验的小伙伴另一种视角:把URI当作客户端内置函数的一种调用方式。

内置功能集
叮铛提供了许多通用的功能,让大家开箱即用,例如会员系统、权限系统、注册、登录、评论、支付、推送等。这些功能在各个应用中的表现大同小异,因此,叮铛把它们做成固化的功能,方便开发者使用。

叮铛提供的通用功能均保留有一定的可扩展能力,让大家根据实际需求来做更个性化的调整,例如:会员字段允许增加自定义字段、任何数据都可以摇身一变变成商品等等。

部份内置功能默认开启,其余功能需要在叮铛应用制作后台的功能菜单中打开。更详尽的功能介绍与使用方式,见【内置功能】一节。

三、叮铛应用的二次开发

零代码开发是叮铛的终极目标,但现阶段仍然会有一些需求在叮铛上是暂时做不出来,为解决这个问题,叮铛成立了专门的开放平台组。

如果叮铛提供的能力仍然不能满足需要,如果你恰好具备一定的开发能力,叮铛应用开发平台能让二次开发。开放平台提供以下几种二次开发的途径:

H5接入,叮铛提供了JSSDK,部分在叮铛应用暂不能实现的app页面,可使用H5来开发,嵌入到制作的app中。
双向SDK:a.叮铛提供插件开发套件,让开发者开发符合叮铛标准的原生插件,上传到开发者自己的插件库,与制作的app进行打包。b.叮铛还提供把制作好的app页面导出为SDK,被开发者整合进他们原有的自主研发的app当中
第三方数据的引入。如果开发者有自己的业务服务器,可以使用叮铛的数据引入机制,既能让你的数据保存在自己的服务器上,又能让你享受叮铛制作app的便利。
生成可交付的代码。遇到需要交付代码的客户?我们可以搞定,叮铛可以为你生成具备交付能力的代码。

收起阅读 »

mui APP开发的几点心得

mui

这几天潜心研究MUI,并做了一个不大不小的项目,一些经验和各位分享。
前端:MUI + JQ
后端:PHP+MYSQL

  1. 能用JQ还是尽量用JQ吧,毕竟现在手机性能越来越好,空间也越来越大,JQ封装了很多方法用起来很方便,建议各位自行权衡。MUI选择器 方法也不错,与用户交互的地方都做了很多美化,两者结合用。

  1. 手机的界面,一般是显示两个webview,我的主页面就是一个index.html 只做页头和页脚,其它webview在中间切来切去。所以我的项目,显示的webview永远只有两个。所以,每一次切换webview,我都把两个之外的webview全部销毁掉。理由是,大多的webview是占用资源的,特别是有些webview页面上,有很多实时项目,需要不断从服务器读取数据,如果不销毁,手机和服务器压力都很大。

  1. 引入JQ后,一般的写法如下:
    mui.plusReady(function() {
    $(function() {
    todo....
    })
    })
    4.尽量自定义属性,特别是对于URL,我习惯用page='index.html',因为你搞不清楚哪个href是可以跳转,哪个是不跳转的
  2. 全程都没用preload,webview开启、切换,转场都很流畅,手机是华为900块钱一台的。
  3. mui自带的字体库 图标太少了点,可以对外开放,叫更多的人来补充。
  4. mui的教程,特别是入门 提高的系统性教程,官方应该录制一些。
  5. 官方的QQ群貌似也没有,建议建几个这样的群,好东西用的人越多越好。


继续阅读 »

这几天潜心研究MUI,并做了一个不大不小的项目,一些经验和各位分享。
前端:MUI + JQ
后端:PHP+MYSQL

  1. 能用JQ还是尽量用JQ吧,毕竟现在手机性能越来越好,空间也越来越大,JQ封装了很多方法用起来很方便,建议各位自行权衡。MUI选择器 方法也不错,与用户交互的地方都做了很多美化,两者结合用。

  1. 手机的界面,一般是显示两个webview,我的主页面就是一个index.html 只做页头和页脚,其它webview在中间切来切去。所以我的项目,显示的webview永远只有两个。所以,每一次切换webview,我都把两个之外的webview全部销毁掉。理由是,大多的webview是占用资源的,特别是有些webview页面上,有很多实时项目,需要不断从服务器读取数据,如果不销毁,手机和服务器压力都很大。

  1. 引入JQ后,一般的写法如下:
    mui.plusReady(function() {
    $(function() {
    todo....
    })
    })
    4.尽量自定义属性,特别是对于URL,我习惯用page='index.html',因为你搞不清楚哪个href是可以跳转,哪个是不跳转的
  2. 全程都没用preload,webview开启、切换,转场都很流畅,手机是华为900块钱一台的。
  3. mui自带的字体库 图标太少了点,可以对外开放,叫更多的人来补充。
  4. mui的教程,特别是入门 提高的系统性教程,官方应该录制一些。
  5. 官方的QQ群貌似也没有,建议建几个这样的群,好东西用的人越多越好。


收起阅读 »

前端老司机 带队接单

多年开发经验,国内主流混合开发框架熟练运用,有需求联系 646676665

多年开发经验,国内主流混合开发框架熟练运用,有需求联系 646676665

如何转让应用

转让项目 转让应用 开发者中心

> 文档已迁移至新链接:https://uniapp.dcloud.net.cn/dev/app/transfer.html
> 如有疑问,可以单独发贴咨询。

继续阅读 »

> 文档已迁移至新链接:https://uniapp.dcloud.net.cn/dev/app/transfer.html
> 如有疑问,可以单独发贴咨询。

收起阅读 »

如何授权应用(设置协作者)

协作者 流应用 开发者中心 授权应用

> 文档已迁移至新链接:https://uniapp.dcloud.net.cn/dev/app/add-member.html
> 如有疑问,可以单独发贴咨询。

继续阅读 »

> 文档已迁移至新链接:https://uniapp.dcloud.net.cn/dev/app/add-member.html
> 如有疑问,可以单独发贴咨询。

收起阅读 »

上拉加载,不要拉到底才开始加载更多数据

更新MUI

官方的原生,上拉加载,每次都是拉到底才能触发加载事件, 不能拉到快离底部一定距离后就开始加载了,不需要用户等待


mui.init({  
                pullRefresh: {  
                    container: '#pullrefresh',  
                    down: {  
                        style:'circle',  
                        callback: pulldownRefresh  
                    },  
                    up: {  
                        contentrefresh: '正在加载...',  
                        callback: pullupRefresh  
                    }  
                }  
            });  

解决方案是: 要修改mui.js 文件,

  _init: function() {  
                var self = this;  
                //document.addEventListener('plusscrollbottom', this);  
                window.addEventListener('dragup', self);  
                document.addEventListener("plusscrollbottom", self);  
                self.scrollInterval = window.setInterval(function() {  
                    if (self.isScroll && !self.loading)   
                    {  
                 if (window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight)   
                        {  
                        self.isScroll = false; //放在这里是因为快速滚动的话,有可能检测时,还没到底,所以只要有滚动,没到底之前一直检测高度变化  
                            if (self.bottomPocket) {  
                                self.pullupLoading();  
                            }  
                        }  
                    }  
                }, 100);  
            }  

//修改 这一句, if (window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight)  , 官方写死的,+10,差不多拉到底才触发, 如果想让到一定距离后就触发,可以修改这个数值,  建议官方可以,整合到方法里去,可以自由设置。
继续阅读 »

官方的原生,上拉加载,每次都是拉到底才能触发加载事件, 不能拉到快离底部一定距离后就开始加载了,不需要用户等待


mui.init({  
                pullRefresh: {  
                    container: '#pullrefresh',  
                    down: {  
                        style:'circle',  
                        callback: pulldownRefresh  
                    },  
                    up: {  
                        contentrefresh: '正在加载...',  
                        callback: pullupRefresh  
                    }  
                }  
            });  

解决方案是: 要修改mui.js 文件,

  _init: function() {  
                var self = this;  
                //document.addEventListener('plusscrollbottom', this);  
                window.addEventListener('dragup', self);  
                document.addEventListener("plusscrollbottom", self);  
                self.scrollInterval = window.setInterval(function() {  
                    if (self.isScroll && !self.loading)   
                    {  
                 if (window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight)   
                        {  
                        self.isScroll = false; //放在这里是因为快速滚动的话,有可能检测时,还没到底,所以只要有滚动,没到底之前一直检测高度变化  
                            if (self.bottomPocket) {  
                                self.pullupLoading();  
                            }  
                        }  
                    }  
                }, 100);  
            }  

//修改 这一句, if (window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight)  , 官方写死的,+10,差不多拉到底才触发, 如果想让到一定距离后就触发,可以修改这个数值,  建议官方可以,整合到方法里去,可以自由设置。
收起阅读 »

安利一个mui的教学视频,hcoder刘海君老师的免费的公开课,帮助大家尽快掌握mui

安利一个mui的教学视频,hcoder刘海君老师的免费的公开课,帮助大家尽快掌握mui

课程地址: https://ke.qq.com/course/203400

接触(一)
【录播】MUI 介绍、新项目创建、 基础布局(13分钟)
【录播】MUI - accordion(折叠面板)、button(10分钟)
【录播】MUI - actionsheet(操作表)、badge(13分钟)
【录播】MUI - 复选框、单选框、使用js获取选择值(15分钟)
【录播】MUI - datepicker(时间选择器)(19分钟)
02
MUI 全接触(二)
【录播】MUI - dialog对话框、ipnut (表单)(23分钟)
【录播】MUI - slide(轮播组件)(17分钟)
【录播】MUI - list(列表/图文列表)(8分钟)
【录播】MUI - progressbar、滑块及switch(19分钟)
【录播】MUI - cardview、mask(遮罩蒙版)(13分钟)
03
MUI 全接触 (三)
【录播】MUI - 窗口管理及窗口之间的数据传递(30分钟)
【录播】MUI - 事件管理及自定义事件详解(26分钟)
【录播】APP与服务器之间的交互原理、MUI Ajax使用(22分钟)

继续阅读 »

安利一个mui的教学视频,hcoder刘海君老师的免费的公开课,帮助大家尽快掌握mui

课程地址: https://ke.qq.com/course/203400

接触(一)
【录播】MUI 介绍、新项目创建、 基础布局(13分钟)
【录播】MUI - accordion(折叠面板)、button(10分钟)
【录播】MUI - actionsheet(操作表)、badge(13分钟)
【录播】MUI - 复选框、单选框、使用js获取选择值(15分钟)
【录播】MUI - datepicker(时间选择器)(19分钟)
02
MUI 全接触(二)
【录播】MUI - dialog对话框、ipnut (表单)(23分钟)
【录播】MUI - slide(轮播组件)(17分钟)
【录播】MUI - list(列表/图文列表)(8分钟)
【录播】MUI - progressbar、滑块及switch(19分钟)
【录播】MUI - cardview、mask(遮罩蒙版)(13分钟)
03
MUI 全接触 (三)
【录播】MUI - 窗口管理及窗口之间的数据传递(30分钟)
【录播】MUI - 事件管理及自定义事件详解(26分钟)
【录播】APP与服务器之间的交互原理、MUI Ajax使用(22分钟)

收起阅读 »

分享一个mui扩展插件mui.showLoading加载框

showWaiting

写在前面:
好像mui目前dialog系列唯独缺少showLoading加载框(加载中)组件,为了统一组件样式和体验,写了这么一个扩展插件。
CSS和JS代码耦合性应该还是较低的,不妥之处欢迎指教!
优点:可以同时兼容Html5和plus,不必为不同环境单独分别Loading组件。
缺点:在页面嵌套情况下,遮罩仅对当前页面起作用。

使用方法:
显示加载框:

mui.showLoading("正在加载..","div"); //加载文字和类型,plus环境中类型为div时强制以div方式显示

隐藏加载框:

mui.hideLoading(callback);//隐藏后的回调函数

注意:
加载框只会显示一个,多次调用showLoading只会显示最后一次调用的内容。

Javascript代码:

//扩展mui.showLoading  
(function($, window) {  
    //显示加载框  
    $.showLoading = function(message,type) {  
        if ($.os.plus && type !== 'div') {  
            $.plusReady(function() {  
                plus.nativeUI.showWaiting(message);  
            });  
        } else {  
            var html = '';  
            html += '<i class="mui-spinner mui-spinner-white"></i>';  
            html += '<p class="text">' + (message || "数据加载中") + '</p>';  

            //遮罩层  
            var mask=document.getElementsByClassName("mui-show-loading-mask");  
            if(mask.length==0){  
                mask = document.createElement('div');  
                mask.classList.add("mui-show-loading-mask");  
                document.body.appendChild(mask);  
                mask.addEventListener("touchmove", function(e){e.stopPropagation();e.preventDefault();});  
            }else{  
                mask[0].classList.remove("mui-show-loading-mask-hidden");  
            }  
            //加载框  
            var toast=document.getElementsByClassName("mui-show-loading");  
            if(toast.length==0){  
                toast = document.createElement('div');  
                toast.classList.add("mui-show-loading");  
                toast.classList.add('loading-visible');  
                document.body.appendChild(toast);  
                toast.innerHTML = html;  
                toast.addEventListener("touchmove", function(e){e.stopPropagation();e.preventDefault();});  
            }else{  
                toast[0].innerHTML = html;  
                toast[0].classList.add("loading-visible");  
            }  
        }     
    };  

    //隐藏加载框  
      $.hideLoading = function(callback) {  
        if ($.os.plus) {  
            $.plusReady(function() {  
                plus.nativeUI.closeWaiting();  
            });  
        }   
        var mask=document.getElementsByClassName("mui-show-loading-mask");  
        var toast=document.getElementsByClassName("mui-show-loading");  
        if(mask.length>0){  
            mask[0].classList.add("mui-show-loading-mask-hidden");  
        }  
        if(toast.length>0){  
            toast[0].classList.remove("loading-visible");  
            callback && callback();  
        }  
      }  
})(mui, window);

CSS代码

/*----------------mui.showLoading---------------*/  
.mui-show-loading {  
    position: fixed;  
    padding: 5px;  
    width: 120px;  
    min-height: 120px;  
    top: 45%;  
    left: 50%;  
    margin-left: -60px;  
    background: rgba(0, 0, 0, 0.6);  
    text-align: center;  
    border-radius: 5px;  
    color: #FFFFFF;  
    visibility: hidden;  
    margin: 0;  
    z-index: 2000;  

    -webkit-transition-duration: .2s;  
    transition-duration: .2s;  
    opacity: 0;  
    -webkit-transform: scale(0.9) translate(-50%, -50%);  
    transform: scale(0.9) translate(-50%, -50%);  
    -webkit-transform-origin: 0 0;  
    transform-origin: 0 0;  
}  
.mui-show-loading.loading-visible {  
    opacity: 1;  
    visibility: visible;  
    -webkit-transform: scale(1) translate(-50%, -50%);  
    transform: scale(1) translate(-50%, -50%);  
}  
.mui-show-loading .mui-spinner{  
    margin-top: 24px;  
    width: 36px;  
    height: 36px;  
}  
.mui-show-loading .text {  
    line-height: 1.6;  
    font-family: -apple-system-font,"Helvetica Neue",sans-serif;  
    font-size: 14px;  
    margin: 10px 0 0;  
    color: #fff;  
}  

.mui-show-loading-mask {  
  position: fixed;  
  z-index: 1000;  
  top: 0;  
  right: 0;  
  left: 0;  
  bottom: 0;  
}  
.mui-show-loading-mask-hidden{  
    display: none !important;  
}

预览效果:

PS
我搞不懂为什么这个编辑器这么渣~

继续阅读 »

写在前面:
好像mui目前dialog系列唯独缺少showLoading加载框(加载中)组件,为了统一组件样式和体验,写了这么一个扩展插件。
CSS和JS代码耦合性应该还是较低的,不妥之处欢迎指教!
优点:可以同时兼容Html5和plus,不必为不同环境单独分别Loading组件。
缺点:在页面嵌套情况下,遮罩仅对当前页面起作用。

使用方法:
显示加载框:

mui.showLoading("正在加载..","div"); //加载文字和类型,plus环境中类型为div时强制以div方式显示

隐藏加载框:

mui.hideLoading(callback);//隐藏后的回调函数

注意:
加载框只会显示一个,多次调用showLoading只会显示最后一次调用的内容。

Javascript代码:

//扩展mui.showLoading  
(function($, window) {  
    //显示加载框  
    $.showLoading = function(message,type) {  
        if ($.os.plus && type !== 'div') {  
            $.plusReady(function() {  
                plus.nativeUI.showWaiting(message);  
            });  
        } else {  
            var html = '';  
            html += '<i class="mui-spinner mui-spinner-white"></i>';  
            html += '<p class="text">' + (message || "数据加载中") + '</p>';  

            //遮罩层  
            var mask=document.getElementsByClassName("mui-show-loading-mask");  
            if(mask.length==0){  
                mask = document.createElement('div');  
                mask.classList.add("mui-show-loading-mask");  
                document.body.appendChild(mask);  
                mask.addEventListener("touchmove", function(e){e.stopPropagation();e.preventDefault();});  
            }else{  
                mask[0].classList.remove("mui-show-loading-mask-hidden");  
            }  
            //加载框  
            var toast=document.getElementsByClassName("mui-show-loading");  
            if(toast.length==0){  
                toast = document.createElement('div');  
                toast.classList.add("mui-show-loading");  
                toast.classList.add('loading-visible');  
                document.body.appendChild(toast);  
                toast.innerHTML = html;  
                toast.addEventListener("touchmove", function(e){e.stopPropagation();e.preventDefault();});  
            }else{  
                toast[0].innerHTML = html;  
                toast[0].classList.add("loading-visible");  
            }  
        }     
    };  

    //隐藏加载框  
      $.hideLoading = function(callback) {  
        if ($.os.plus) {  
            $.plusReady(function() {  
                plus.nativeUI.closeWaiting();  
            });  
        }   
        var mask=document.getElementsByClassName("mui-show-loading-mask");  
        var toast=document.getElementsByClassName("mui-show-loading");  
        if(mask.length>0){  
            mask[0].classList.add("mui-show-loading-mask-hidden");  
        }  
        if(toast.length>0){  
            toast[0].classList.remove("loading-visible");  
            callback && callback();  
        }  
      }  
})(mui, window);

CSS代码

/*----------------mui.showLoading---------------*/  
.mui-show-loading {  
    position: fixed;  
    padding: 5px;  
    width: 120px;  
    min-height: 120px;  
    top: 45%;  
    left: 50%;  
    margin-left: -60px;  
    background: rgba(0, 0, 0, 0.6);  
    text-align: center;  
    border-radius: 5px;  
    color: #FFFFFF;  
    visibility: hidden;  
    margin: 0;  
    z-index: 2000;  

    -webkit-transition-duration: .2s;  
    transition-duration: .2s;  
    opacity: 0;  
    -webkit-transform: scale(0.9) translate(-50%, -50%);  
    transform: scale(0.9) translate(-50%, -50%);  
    -webkit-transform-origin: 0 0;  
    transform-origin: 0 0;  
}  
.mui-show-loading.loading-visible {  
    opacity: 1;  
    visibility: visible;  
    -webkit-transform: scale(1) translate(-50%, -50%);  
    transform: scale(1) translate(-50%, -50%);  
}  
.mui-show-loading .mui-spinner{  
    margin-top: 24px;  
    width: 36px;  
    height: 36px;  
}  
.mui-show-loading .text {  
    line-height: 1.6;  
    font-family: -apple-system-font,"Helvetica Neue",sans-serif;  
    font-size: 14px;  
    margin: 10px 0 0;  
    color: #fff;  
}  

.mui-show-loading-mask {  
  position: fixed;  
  z-index: 1000;  
  top: 0;  
  right: 0;  
  left: 0;  
  bottom: 0;  
}  
.mui-show-loading-mask-hidden{  
    display: none !important;  
}

预览效果:

PS
我搞不懂为什么这个编辑器这么渣~

收起阅读 »