APICloud APP开发规范

    2-1. 项目架构

    2-1-2. 使用APICloud五大组件进行App的UI架构设计

    2-1-4. 使用api方法打开窗口

    2-2. 文件命名

    2-2-2. CSS类型、JS类型文件

    2-2-4. Image类型文件

    2-4. UI页面

    2-5-1. 数据请求

    2-5-3. 页面间的跨域数据传值

    3. 通用编码原则

    3-1-1. 样式编码格式

    3-1-3. 引号使用

    3-1-5. 性能优化

    3-2-1. 元素(标签)

    3-2-3. 属性的定义,统一使用双引号

    3-3. JavaScript 编码原则

    3-3-2. 注释

    为了提升APICloud App的程序质量、程序性能及用户体验,同时也为了统一团队代码风格,优化团队协作效率,特制定及推出本规范。

    本规范基于原APICloud项目编码规范编制,属于APICloud项目编码规范的升级迭代版本。本规范适用于通过APICloud平台开发App项目的开发实施团队,作用于软件项目开发阶段和后期维护阶段。

    本规范约定一下几个前缀词汇用来表明对于当前条款的要求执行力度,具体如下:

    • 【必须】表示必须遵守,包含此前缀的规范条款,要求开发者在开发者必须按此规范的要求进行开发,通常违反此类条款,都会对最终App的性能或用户体验产生影响;

    • 【推荐】表示推荐执行,包含此前缀的规范条款,只是推荐开发者去遵守执行,通常此类条款描述的内容有多种可行性方案,开发者可根据自身实际考虑是否采纳执行;

    2.1.1. 【推荐】基本原则

    项目的widget包结构应遵循APICloud官方模版提供的widget包的结构体系,即初始项目应包含有css、html、script、image、res等文件夹,应用文件应严格按照文件属性归档到对应的文件夹内

    • css目录下放外部样式文件,“.css”文件应全部放置于css文件夹内

    • html目录下放页面代码,“.html”文件应放置于html文件夹内

    • script目录下放外部脚本文件,“.js”文件应放置于script文件夹内

    • image目录下放组成UI的图标、背景图等

    • res目录下放其它用到的资源,项目内正式使用的资源类文件,如音频、视频及其他格式文件应放置于res文件夹内

    • icon文件夹用来存放App图标,主要用于测试版本使用,应在编译正式上架版本前删除

    • launch文件夹用来存放App欢迎图,主要用于测试版本使用,应在编译正式上架版本前删除

    • 出于测试目的,添加的测试图片、音频、视频等文件应内单独创建文件夹放置,并在编译正式上架版本前删除

    • APICloud应用与一般前端web页面不同,用于单独页面的css样式代码和js代码,建议直接在该页面的html文件内书写,不需要将代码分离出来单独创建与文件同名的“.css”和“.js”文件

    • 基于上条原则,css文件夹主要放置可被多个页面引用的通用样式的“.css”文件;js文件夹主要放置可被多个页面引用的公用“.js”文件或功能独立可复用的“.js”文件

    • 原则上不要修改项目创建的自动建立的官方的api.css及api.js文件,以防该文件后续出现迭代版本时无法顺利替换迭代

    返回目录

    2.1.2. 【必须】使用APICloud五大组件进行App的架构设计

    APICloud五大组件为、LayoutWindowFrameUIModules

    项目窗口应使用window+frame的结构,静态的无需频繁更新的title和导航栏、页脚等部分放在window中,需要实时更新,响应用户操作的放在frame

    SPA(单页面)模式,不适合App开发,DIV+JS的窗口切换影响用户体验。APICloud的UI结构设计可以从整体上解决H5在Interaction、Animation、Render方面的性能问题

    2.1.3. 【推荐】多个高度一致,位置一致的窗口使用frameGroup

    使用frameGroup可以提高一组frame之间互相切换的性能及体验

    • 根据实际业务逻辑,合理配置预加载的Frame数量

      api.openFrameGroup中的预加载控制参数

    • 合理设置frameGroup中每个Frame页面的刷新机制

      根据业务需要,考虑是手动下拉刷新、还是切换Framegroup页面时自动触发刷新、还是在页面的viewappear事件中添加自动刷新逻辑

    2.1.4. 使用api方法打开窗口

    2.1.4.1 【必须】使用api.openFrame/api.openFrameGroup时,参数rect尺寸应使用margin布局,这样frame页面高度会动态跟随在屏幕高度变化。

    App在不同手机上运行,会出现屏幕尺寸发生变化的情况。如iPhone手机共享热点时,会占用页面顶部空间,华为手机的虚拟按键会占用页面底部空间,这些导致屏幕高度发生变化的事件都有可能在frame页面打开以后发生,如果不使用margin布局,就会出现页面显示错误,导致项目Bug产生。

    参考示例代码:

    1. var eHeader = $api.byId('header');
    2. var headerHeight = $api.fixStatusBar(eHeader);
    3. var eFooter = $api.byId('footer');
    4. var footerHeight = $api.fixTabBar(eFooter);
    5. api.openFrame({
    6. name: 'page',
    7. url: './page.html',
    8. rect: {
    9. marginLeft: 0,
    10. marginRight: 0,
    11. marginTop: headerHeight,
    12. marginBottom: footerHeight
    13. }
    14. });

    2.1.4.2 【推荐】开发者要根据实际应用情景,注意bounces(控制页面弹动),delay(延迟页面显示),reload(页面重载),customRefreshHeader(自定义下拉刷新)几个参数的配置和使用

    2.1.4.3 【推荐】如无特殊使用场景逻辑限制,应开启iOS的侧滑返回功能和点击状态栏跳转页面顶部功能

    1. slidBackEnabled:
    2. 类型:布尔
    3. 默认值:true
    4. 描述:(可选项)是否支持滑动返回。iOS7.0及以上系统中,在新打开的页面中向右滑动,可以返回到上一个页面,该字段只iOS有效
    5. scrollToTop
    6. 类型:布尔
    7. 默认值:false
    8. 描述:(可选项)当点击状态栏,页面是否滚动到顶部。若当前屏幕上不止一个页面的scrollToTop属性为true,则所有的都不会起作用。只iOS有效
    9. 此效果在FrameGroup中使用的时候要注意确保只有当前显示的FramescrollToTop属性为true,其它FramescrollToTop属性为false

    2.1.4.4 【必须】对页面的返回事件进行逻辑处理时,应考虑屏蔽iOS的侧滑机制和编写android手机的物理返回键点击事件逻辑

    2.1.4.5 【推荐】如果没有特别要求尽量使用平台默认的动画效果,即api.openWin时不指定动画类型,使用默认值

    • 无论是在Android还是iOS上,APICloud引擎会从整体上保证默认的窗口动画类型是性能最好的

    • 如果窗体所加载的静态网页内容比较多(如:初始的Dom树很大或图片很多),在Android平台上openWindow的时候可以尝试使用movein或fade的动画类型

    2.1.4.6 【推荐】三星、小米等大屏Android6.0及以上手机,可以尝试在云编译的时候选择使用Android引擎渲染优化版本

    2.1.5. 【推荐】标准APICloud App页面按以下页面编码结构进行开发

    1. <!doctype html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,initial-scale=1.0,width=device-width" />
    6. <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
    7. <title>Hello App</title>
    8. <link rel="stylesheet" type="text/css" href="./css/api.css" />
    9. <style type="text/css">
    10. /* CSS样式代码 */
    11. </style>
    12. </head>
    13. <body>
    14. <!-- HTML静态页面代码 -->
    15. </body>
    16. <script type="text/javascript" src="./script/api.js"></script>
    17. <script type="text/javascript" src="./script/db.js"></script>
    18. <script type="text/javascript">
    19. /* JS逻辑代码 */
    20. </script>
    21. </html>

    返回目录

    2.2. 文件命名

    2.2.1. 基本原则

    • 【必须】全部使用小写英文字母及下划线进行命名

      1. 禁止使用大写英文字母,包含大写字母的资源文件在某些手机上可能存在兼容问题,出现无法找到资源的错误。
      2. 禁止使用中文字符,原生系统内部不支持带中文字符的资源名
      3. 例如在自定义Loader中运行没有问题,但云编译的包就有问题,出现页面无法加载或资源找不到等问题,通常就是使用了中文或大写的文件命名。因为官方Loader或自定义LoaderWidget是存放在SDCard中,而云编译后的安装包Widget是存在应用的沙箱中,沙箱中是要采用的原生系统的内部资源文件管理机制
    • 【推荐】采用英文单词作为语义化内容,语义单词应准确精练,能够体现文件内容或功能

      1. login.html
    • 【推荐】语义英文单词之间使用下划线_进行连接

    2.2.2. CSS类型、JS类型文件

    • 【推荐】引用第三方的CSS框架、JS框架,直接使用原名称即可

    • 【推荐】开发人员封装的通用CSS、JS文件,文件命名语义应能体现出此文件的功能用途

    2.2.3. HTML类型文件

    • 【推荐】页面窗口属性为Frame时,文件名尾部建议加入frm标识,如person_frm.html

    • 【推荐】页面窗口属性为Window时,无须追加尾部标识说明

    • 【推荐】语义化、层级化进行文件命名

      文件名的英文单词语义应当能够表达出当前页面功能内容,及页面间的父子层级结构。建议取消使用文件夹方式区分html页面文件,可改为将文件夹名称作为带有语义的单词,使用下划线 _ 连接的方式给文件命名

      1. 例如:
      2. App主页面为home(首页),message(消息),my(我的)页面,在首页页面内有搜索按钮,点击跳转到搜索页面
      3. 原来我们可以建立在HTML文件夹中建立3个文件夹,如homemessagemy,然后在home文件夹下再建立search.html文件,如果search这个模块页面很多,也有可能再建立search文件夹,然后再在这个serach文件夹内建立main.html文件
      4. 现在我们可以建议改成这样
      5. home_search.html,home_search_frm.htmlhome_search_main.html
      6. 这样做的好处是所有页面都在html下,是平级关系,这样在引用.css文件和.js文件时就不需要过多考虑文件之间的层级关系,并且有利于页面的复用和通用方法的封装

    返回目录

    2.2.4. Imgae类型文件

    • 【推荐】icon图标类图片,使用icon标识开头,如icon_person_avatar.png用户头像

    • 【推荐】背景类图片,使用bg标识开头, 如bg_person.jpg用户背景

    • 【推荐】占位图、缺省图、默认图等此类图标,使用default标识开头,此优先级高于上述icon、bg,如default_icon_avatar.png默认头像

    • 【推荐】临时测试图片,使用test标识开头,如test_house.png

    2.3. 项目安全

    2.3.1 【必须】用户输入的密码应进行哈希算法(如MD5SHA1等不可逆算法)加密处理,应避免明文发送和本地存储

    2.3.2 【推荐】项目在条件允许的情况下,网络请求优先使用HTTPS协议,以保障项目的通讯数据安全

    • config.xml中的checkSslTrusted配置项配置是否检查https证书是受信任的

    • config.xml中的配置是否校验应用证书。若配置为true,应用被重签名后将无法再使用。

    • 支付订单金额应由服务器产生,服务器一定要对支付宝、微信服务器回调的支付结果做最终校验

    • alipay模块要调用payOrder方法来进行支付,自己处理订单信息以及签名过程;不要使用config接口和`pay``接口把订单信息以及签名过程交予模块内部处理(官方提供此种支付方式只是为了方便开发者调试)

    2.3.4 【必须】选择全包加密进行云编译

    开发过程中每次云编译的无论测试包还是正式包都建议选择全包加密,因为在APICloud定制平台上,客户可以全程监控项目的实施过程,可以查看代码提交纪录,但是没有获取代码的权限;客户可以查看云编译纪录,如果编译的安装包没有使用全包加密则客户可能通过解压安装包轻松获取App的H5源码,从而影响后续项目款的按时支付。

    • config.xml中的access配置项可以配置在哪些类型的页面里面可以访问APICloud的扩展API方法,可访问域的设置以及越狱限制等。

    2.3.5 【推荐】对重要参数变量进行必要的加密处理,对重要的常量数据应放入中,使用api.loadSecureValue方法进行数据读取;

    如第三方SDK模块使用的AppId及SecretKey等涉及项目安全性的重要数据信息及对隐私要求比较高的数据信息在放置在res文件夹中的key.xml文件中,云编译时云服务器会自动加密key.xml文件,从而保证数据的信息安全。

    2.4.1 【必须】严格按照UI尺寸图标注进行页面开发,H5页面的实现要与UI尺寸完全一致,量图优先考虑绝对计量类的单位px,要求精细到0.5px

    1. 当前APICloudUI尺寸图的标注与前端App开发的标注尺寸是2倍的关系
    2. UI尺寸图标注一个分割线的宽度为1px,则开发需要实现0.5px宽的细线

    2.4.2 【必须】页面适配保证图片比例不变,既页面图片元素高度应能根据屏幕宽度进行等比例换算,以保证图片不出现拉伸变形

    2.4.3 【推荐】APICloud项目建议开启“沉浸式”效果,增强App用户体验。

    • 在config.xml文件中配置

      1. <preference name="statusBarAppearance" value="true" />
    • 要根据当前界面的背景颜色,通过调用api.setStatusBarStyle方法来设置当前状态栏的风格或背景色

    2.4.4 【必须】增加对iPhoneX及类似类型手机的屏幕适配支持

    最新官方的api.js框架中增加了对iPhoneX的屏幕适配方法$api.fixStatusBar$api.fixTabBar,应及时更新api.js文件。

    最新版本api.js文件的获取方法,在官网控制台创建一个Navtive项目,将项目源码下载到本地,项目script文件夹下的api.js就是最新版本的

    2.5. 数据处理

    2.5.1. 数据请求

    2.5.1.1 【必须】应使用api.ajax进行网络数据请求,并且设置合适的超时时间,对超时和请求失败的异常情况应编写相应的处理逻辑代码

    1. 避免使用JavaScript原生ajax方法或其他JavaScript框架封装的ajax方法进行网络请求。因为在云端编译项目版本时,特别是启用代码加密时,会发生异常,导致App出现功能错误
    2. `JQuery``ajax`在开启全包加密的时候就会有问题

    2.5.1.2 【推荐】根据项目业务需求实际情况,合理利用api.ajax的参数可选项

    1. `dataType``charset``headers``returnAll`

    2.5.1.3【推荐】根据实际业务需求,考虑监听网络状态,编写回调处理逻辑,保证项目在不同网络状态下均可合理运行

    1. api下的监听事件:`online``offline``connectionType`

    2.5.1.4 【推荐】考虑对api.ajax请求进行适度封装

    api.ajax请求在项目开发中的使用范围广、使用频率高,并且ajax请求及响应部分均包含有可被抽象定义的参数或逻辑,所以建议对ajax请求进行合理的适度封装,使数据交互逻辑层次更清晰、代码使用更高效,同时也利于后期的维护开发。

    例如对请求接口地址url中的根路径进行抽象定义。

    1. ajax的封装方法中把根路径为一个内置参数对象,这样以后服务器地址改变,如ip地址改为域名地址或者域名更换时,我们就不需要逐一修改每一个请求方法,只需要简单的修改封装方法内的根路径内置参数的变量值即可。

    2.5.1.5 【必须】编制ajax请求的异常处理逻辑,保证App程序的健壮性和良好的用户体验

    api.ajax请求回调错误码信息:

    1. 0 //连接错误
    2. 1 //超时
    3. 2 //授权错误
    4. 3 //数据类型错误

    2.5.1.6 【推荐】对于页面内容需要等待ajax请求完成后加载的页面,应显示进度状态提示,提升用户体验

    2.5.1.7 【推荐】请求响应数据的缓存处理

    如页面内的ajax请求方法使用频繁,且请求的响应数据内容变化频率低,则应对此请求的响应数据进行本地缓存处理,以提高应用在断网或网速不佳时的页面加载速度,提升用户体验。

    • 对于GET类型的请求方式,可将cache参数设置为trueapi.ajax将自动对此Get请求进行缓存处理

      1. cache
      2. 类型:布尔
      3. 默认值:false
      4. 描述:(可选项)是否缓存,若缓存,下次没网络时请求则会使用缓存,仅在get请求有效
    • 对于POST类型的请求方式,根据实际业务场景需求,如不涉及复杂业务,返回的仅是列表展示类数据,建议自行缓存数据,优化数据交互逻辑。

    2.5.2. 数据本地化

    【推荐】为了提高用户阅读使用体验,应考虑对请求获取的网络数据进行本地缓存处理,以方便实现预加载或离线加载功能。

    • 少量数据可以使用$api.setStorageapi.setPrefs方式进行本地数据缓存

      1. $api.setStorage可以执行保存JSON对象,api.setPrefs则不能,必须将JSON对象序列化为JSON字符串后方可保存
      2. api.setPrefs缓存的数据,在iOS通过数据线进行应用备份时,数据会同步备份,$api.setStorage则不会
    • 大容量数据可以使用读写文件的方式保存,或使用以数据库方式保存数据

      1. 文件读写可使用api.readFileapi.writeFile或使用fs模块方法
      2. 本地数据库操作可以使用db模块

    2.5.3. 页面间的跨域数据传值

    • 【推荐】根据业务场景逻辑,选择合适的方式进行数据传输

      • api.openWinapi.openFrame时,使用api.pageParam参数进行传值

      • 将数据本地化后,在其他页面直接进行缓存读取,获取数据值

      • 使用api.addEventListener监听事件,使用api.sendEvent方法发送事件通知,同时携带传值的参数

      • 使用api.execScript通过函数形参进行传值

    • 【推荐】优先考虑使用api.pageParam,但要避免使用过大的pageParam

    • 【推荐】尽可能的减少监听方法的使用以降低手机cpu的线程、性能消耗

    • 【必须】避免问号传参,问号传参有找不到资源的兼容风险

      不要使用使用URL+?的形式进行参数的传递,此方式在Android上存在兼容问题

    • 【推荐】页面间逻辑交互,优先使用api.execScript,必要时再使用监听方法

      当使用JSON对象作为api.execScript方法的形参时,须将JSON对象序列化为字符串后再作为形参传递

    返回目录

    2.6. 编码优化

    2.6.1 【推荐】输入框位于设备屏幕下半部份的应用场景,config.xml中的的键盘弹出模式参数务必设置为resize模式,或者使用UIInput相关模块。

    2.6.2 【推荐】为了让应用看起来更接近原生,尽量配置config.xml中的参数来隐藏iOS键盘上面的工具条。也可以在openWinopenFrame的时候通过softInputBarEnabled参数来单独指定

    2.6.3 【推荐】引入外部字体会对程序运行性能产生影响,如必须引入字体,应控制外部字体文件的大小,字体文件不宜过大

    • Android上默认有3种字体:sans,serif,monospace,在开发人员不指定的情况下,默认为sans,这3种字体在开发过程中都是通过字体名进行引用,系统会自动对应到内置字体文件。但是,对于外部的字体文件,Android上无法实现通过引擎配置后成为内置的字体文件,只能通过@font-face的方式在每个页面中重复加载,每一个要使用外部字体的WindowFrame都要引入一遍,如果字体体积过大会占用大量内存,并且影响页面的加载速度。

    • iOS可以在config.xml文件中进行,配置完成后就可以像系统内置字体一样在页面中指定了,无需在每个WindowFrame中通过@font-face的方式引入

    2.6.4 【推荐】文件、数据库、偏好设置等操作,如果业务逻辑需要等待获取到结果内容后进行下一步操作时,推荐使用同步接口(方法名增加Sync后缀)来简化代码的实现,解决异步callback层次过深的问题

    2.6.5 【必须】正式版本应关闭/删除测试联调是使用的console.log控制台打印显示方法,严禁正式版本出现供测试联调使用的alert信息

    • 可考虑封装统一的日志打印显示方法在测试联调时使用,方便控制日志打印功能的开启和关闭

    • 测试联调优先使用控制台打印命令console.log,避免或减少使用alert方法进行测试联调,防止正式版本有遗漏,弹出测试数据信息。

    2.6.5 【推荐】对于内容数据存在动态更新情况的页面,应实现页面下拉刷新功能以保证用户可以手动刷新页面数据

    2.6.6 【推荐】优化用户体验,根据业务场景,考虑实现对App进入后台和回复前台的事件监听和逻辑处理

    2.6.7 【推荐】尽量不对Object,Array拓展原型方法,有可能导致iOS系统的App闪退出现

    2.6.8 【推荐】在异常处理逻辑需要显示异常信息时,根据异常的重要程序选择使用alert或toast方式进行提示

    1. api.alert会阻塞线程,强制用户点击后程序才能继续执行,适合在需要用户明确确认的场景内使用

    2.6.9 【推荐】避免不必要的DOM操作,浏览器遍历DOM元素的代价是昂贵的。当一个元素出现多次时,将它保存在一个变量中

    2.6.10 【推荐】避免使用如jQuery、jQuery Mobile、SenchaTouch、Bootstrap等“重型框架”

    2.6.11 【推荐】窗口关闭处理:开发过程中根据需要处理Android的keyback事件和iOS的回滑手势

    • Android上要在Window中才能监听到keyback事件,Frame中无法监听到keyback事件;

    • 在iOS7以上的系统上可以在openWin的时候通过设置slidBackEnabled参数来实现是否支持回滑手势关闭窗口的功能。

    • 在后台关闭非当前显示页面时,应设置animation:{type:”none”},关闭动画效果方式,以免页面关闭动画影响当前显示页面的渲染,从而降低用户体验;

    2.6.12 【推荐】应尽量减少使用第三方样式、脚本库或框架。

    • 摆脱对 $ 函数的依赖,转变思想,养成自己动手的习惯,移动端对HTML5、CSS3、ECMAScript5支持较好

    • 如某些需求不得不使用一些第三方脚本时,应使用对移动端支持良好、并且目标性强、功能单一的框架

      1. 如:api.jszepto.jsswipe.jsdoT.js
      2. 默认样式设置、DOM操作和字符串处理推荐使用APICloud前端框架(api.jsapi.css

    2.6.13 【必须】窗口切换避免出现任何卡顿、闪屏、白屏等情况;动画效果要求流畅,不能出现丢帧的情况

    1. 要理解并控制窗口好切与界面渲染之间的关系,要适时更新UI,如果WindowFrame中所加载的静态页面内容过多,建议等动画执行完毕再进行页面的加载和渲染。无论是Android还是iOS系统,在进行窗口切换的时候,如果窗体本身正在进行渲染(WindowFrame所加载的网页没有渲染完毕),则会影响切换动画运行的流畅性,出现卡顿或丢帧的情况
    2. 建议在打开WindowFrame的时候,如果所加载的静态网页不能快速的渲染完毕。为了不影响窗体切换动画的执行,可以在切换动画执行完毕后再进行动态数据的加载和界面的刷新

    2.6.14 【推荐】保证页面的加载速度

    • 样式、业务逻辑代码写在html页面中

    • 公用css、js库应尽量小,不要加载无用的css、js

      1. 浏览器内部是解释执行,只要页面中引入了就会加载和解析。
    • 减少使用<link/><script/>标签

      1. 每一个<link/>或<script/>标签浏览器引擎都将有一次同步i/o读写。
    • JavaScript脚本加载

      1. 一段脚本放置在<head>内其加载会影响或阻塞DOM解析,这会造成页面显示的延迟,影响用户体验。如无特殊需要,应将引用的JavaScript文件和页面内编写的JavaScript代码放置于</body>结束标签之后
    • 利用CSS3及HTML5的特性

      1. 应尽量使用CSS3动画、圆角处理、渐变处理、边框、新的input类型等。

    2.6.15 【推荐】避免body级别的背景,以原生的方式高效替代

    • 可在openWin或openFrame时传入bgColor。也可在config.xml中配置全局背景

    • 不建议通过给body元素指定background的方式来实现body级别的背景图片,特别是高清的大背景图片用H5方式实现会严重影响渲染性能

    2.6.16 【必须】编译的正式版本禁止包含项目未使用模块

    1. 编制正式版本前,应检查一下控制台选定的模块是否都在实际代码中使用到了。一些开发者在开发过程中会不断引入一些“预计使用”或"测试使用"的模块,但是在最终的代码中没有使用,这部分模块要云编译的时候去掉,无用的模块不仅仅会增大安装包的体积,还有可能引起于其它模块的冲突或编译选项,造成编译失败
    2. config.xml文件中配置的模块,在控制台无法删除,因为configfeature配置项的forceBind属性默认true,是强制绑定的,可以通过修改config.xml配置中[forceBind属性](http://docs.apicloud.com/Dev-Guide/app-config-manual#15)来解除模块的强制绑定关系

    2.6.17 【必须】沉浸式修复应放在apiready方法中调用实现

    $api.fixStatusBar$api.fixTabBar方法使用了api.safeArea方法,所以进行沉浸式修复需等待全局api引擎对象加载完成后再调用使用,即在API对象加载完成的周期事件apiready方法里调用沉浸式修复逻辑

    2.6.19 【推荐】控制图片尺寸大小,减少内存占用,降低性能损耗

    • 在App中,图片占用过多内存引起程序假死、崩溃、其它多种异常状态的事例数不胜数。应尽量减少图片对内存的占用。

      1. 图片占用内存算法:ram = 图片宽度 x 图片高度 x 4
      2. 分辨率为 200 的图片:200 x 200 x 4 = 160KB
      3. 分辨率为 600 的图片:600 x 600 x 4 = 1.44MB
      4. 相差 9 倍!
    • 图片缩放时会消耗很高的性能,应避免发生。通常根据图片用处选择@2x/@3x图即可

    • 列表中的头像等缩略图,宽高建议控制在250-300px之间,小于这个范围大屏手机容易失真,大于这个范围消耗更多内存和性能

    • 如图片原尺寸无法控制,可通过客户端传参,服务器动态裁剪处理图片尺寸的方式,返回处理后的图片解决上述问题,也可利用第三方云存储现有的缩略图服务,如阿里云的oss。

    2.6.20 【推荐】远程异步加载的图片类页面元素,应考虑在页面数据加载前显示默认占位图。

    1. 该占位图片尺寸大小应满足与UI设计尺寸要求,可让UI设计提供相应尺寸切图

    2.6.21 【推荐】远程异步加载的图片类页面元素,应对图片进行缓存处理。

    1. 标准H5默认的缓存机制存在缺陷,在跨窗口时表现不好,并且存在对所缓存图片的尺寸限制等问题
    2. 所有APICloud应用的图片缓存不能依赖Webview默认的缓存机制,必须手动实现。
    3. api.imageCache方法可以对图片进行本地缓存

    2.6.22 【推荐】列表类页面开发

    • 列表显示内容数据存在动态变化可能时,应实现添加下拉刷新功能

    • api接口支持多页面请求时,应实现上拉加载功能

    • api.refreshHeaderLoading开始刷新方法须由用户下拉动作触发,应避免程序自动调用该方法加载数据,因为这样会导致页面自动模拟下拉动作,显得很突兀

    • 列表获取数据为空时,应显示空数据占位背景图

    • 滚动效果要平滑流畅,不能使用iscroll等JavaScript的方式来实现滚动

      1. 建议使用Window+FrameUI结构,以Native的方式来实现列表页面的滚动
    • 应对按钮的点击事件进行300ms点击延迟响应的消除处理

      浏览器的点击事件触发默认有300ms或更长的延迟。应在绑定每个onclick事件的同时绑定tapmode属性。

      tapmode属性为APICloud为消除300ms延迟的问题专门定制的私有属性。

      具体使用方法如下:

      • 在HTML标签代码中的onclick事件,直接写入tapmode属性

        1. <div tapmode="touched" onclick="fnSelected(this)">好评优先</div>
      • 使用JavaScript动态加载到html页面中的元素的onclick事件事件,除按上条要求书写外,还须使用api.parseTapmode()方法来使tapmode属性生效。

        默认页面加载完成后,引擎会对dom里面的元素进行tapmode属性解析,若是之后用代码创建的dom元素,则需要调用该方法后tapmode属性才会生效

      • api.parseTapmode调用会有性能成本,不需要的情况下不要随便调用

    • 提升点击反馈和点击区域

      • 应给每个tapmode属性赋值一个css样式,实现点击反馈效果。

      • 在移动应用中由于用户的交互形式主要以手指触控为主,与屏幕的接触面较大,应尽量设置大小合理的点击区域以提高用户交互体验,可使用background-size。

    • 增加按钮连续点击的判断逻辑,防止因用户的多次点击引起业务逻辑的多次重复执行,导致不必要的效率损耗和产生逻辑的异常错误

    返回目录

    3.1.1. 样式编码格式

    • 选择器分组时,保持独立的选择器占用一行

    • 声明块的左括号 { 前添加一个空格

    • 声明块的右括号 } 应单独成行

    • 声明语句中的 : 后应添加一个空格

    • 声明语句应以分号 ; 结尾

    • 一般以逗号分隔的属性值,每个逗号后应添加一个空格

    • rgb()、rgba()、hsl()、hsla() 或 rect() 括号内的值,逗号分隔,但逗号后不添加一个空格

    • 对于属性值或颜色参数,省略小于 1 的小数前面的 0 (例如,.5 代替 0.5;-.5px 代替-0.5px)

    • 十六进制值应该全部小写和尽量简写,例如,#fff 代替 #ffffff

    • 避免为 0 值指定单位,例如,用 margin: 0; 代替 margin: 0px

      1. /* 不推荐 */
      2. .selector, .selector-secondary, .selector[type=text] {
      3. padding:15px;
      4. margin:0px 0px 15px;
      5. background-color:rgba(0, 0, 0, 0.5);
      6. box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
      7. }
      8. /* 推荐 */
      9. .selector,
      10. .selector-secondary,
      11. .selector[type="text"] {
      12. padding: 15px;
      13. margin-bottom: 15px;
      14. background-color: rgba(0,0,0,.5);
      15. box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
      16. }

    3.1.2. 声明顺序

    • 相关属性应为一组,推荐的样式编写顺序

      1. Positioning
      2. Box model
      3. Typographic
      4. Visual

      由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位

      盒模型决定了组件的尺寸和位置,因此排在第二位

      其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面

    3.1.3. 引号使用

    • url() 、属性选择符、属性值使用双引号

    3.1.4. Class 和 ID

    • 使用语义化、通用的命名方式

    • 使用连字符中划线 - 作为 ID、Class 名称界定符,不要驼峰命名法和下划线

    • 避免选择器嵌套层级过多,尽量少于 3 级

    • 出于性能考量,在没有必要的情况下避免元素选择器叠加 Class、ID 使用,如果HTML标签修改了,就要再去修改 CSS 代码,不利于后期维护。

      1. 例如
      2. 推荐 #cell-title input{}

    返回目录

    3-1-5. 性能优化

    • Avoid tag selectors (避免标签选择器)

      任何时候尽可能使用 classnames。标签选择器在使用上没有问题,但是其性能上稍弱,并且表意不明确

    • 不滥用 Float

      Float在渲染时计算量比较大,尽量减少使用

    • 提升 CSS 选择器性能

      CSS 选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器。CSS 选择器匹配的机制是从右到左进行规则匹配,我们把最右边选择符称之为关键选择器。

      • 避免使用通用选择器

        1. /* 不推荐 */
        2. .cell * { height: 50px;}

        浏览器匹配文档中所有的元素后分别向上逐级匹配 class 为 content 的元素,直到文档的根节点。因此其匹配开销是非常大的,所以应避免使用关键选择器是通配选择器的情况

      • 避免使用标签或 class 选择器限制 id 选择器

        1. /* 不推荐 */
        2. button#backButton {…}
        3. /* 推荐 */
        4. #newMenuIcon {…}
      • 避免使用标签限制 class 选择器

      • 避免使用多层标签选择器。使用 class 选择器替换,减少css查找

        1. /* 不推荐 */
        2. treeitem[mailfolder="true"] > treerow > treecell {…}
        3. /* 推荐 */
        4. .treecell-mailfolder {…}
      • 避免使用子选择器

        1. /* 不推荐 */
        2. treehead treerow treecell {…}
        3. /* 推荐 */
        4. treehead > treerow > treecell {…}
        5. /* Much to 推荐 */
        6. .treecell-header {…}
      • 使用继承

        1. /* 不推荐 */
        2. #bookmarkMenuItem > .menu-left { list-style-image: url(blah) }
        3. /* 推荐 */
        4. #bookmarkMenuItem { list-style-image: url(blah) }

    3.2. 【推荐】HTML 编码原则

    3.2.1. 元素(标签)

    • 可选的闭合标签(closing tag)需闭合。HTML5 规范中规定了 HTML 标签是可以省略的,例如:

    或 。但从可读性来说,在开发的源文件中最好不要这样做,因为省略标签可能会导致一些问题。

    • 页面实现时应使用语义化标签

      1. headersectionfooternav
    • 编程优化角度出发,尽量减少标签数量

    • 应在 <head> 标签下的 <title> 标签内使用中文对当前页面进行说明,方便后续人员快速定位页面

      1. <head>
      2. ...
      3. <title>登陆页面</title>
      4. ...
      5. </head>

    3.2.2. 属性顺序

    HTML 属性应该按照特定的顺序出现以保证易读性。

    1. id
    2. class
    3. name
    4. data-xxx
    5. src, for, type, href
    6. title, alt
    7. aria-xxx, role
    8. <a id="..." class="..." data-modal="toggle" href="###"></a>
    9. <input class="form-control" type="text">
    10. <img src="..." alt="...">

    3.2.3. 属性的定义,统一使用双引号

    1. <!-- 不推荐 -->
    2. <span id='j-hook' class=text>Google</span>
    3. <!-- 推荐 -->
    4. <span id="j-hook" class="text">Google</span>

    3.2.4. Class 与 ID

    • class 应以功能或内容命名,不以表现形式命名;

    • class 与 id 单词字母小写,多个单词组成时,采用中划线-分隔;

    • 使用唯一的 id 作为 Javascript hook, 同时避免创建无样式信息的 class;

    返回目录

    3.3. 【推荐】JavaScript 编码原则

    3.3.1. 命名

    • 命名区分大小写,允许包含字母、数字、美元符号($)和下划线,但第一个字符不允许是数字,不允许包含空格和其他标点符号

    • 名字应由三个以内的单词组成,控制在 3 至 20 个字母以内

    • 名字应能够标识事物的特性,尽量避免使用没有意义的命名

    • 名字应使用英文单词而不是拼音

    • 名字不应使用缩写,除非它是众所周知的

    • 禁止使用JavaScript关键词、保留字全名

    • 变量, 使用驼峰命名法

      1. var loadingModules = {};
    • 常量, 使用全部字母大写,单词间下划线分隔的命名方式

      1. var HTML_ENTITY = {};
    • 函数, 使用驼峰命名法

    • 函数的参数, 使用驼峰命名法

      1. function stringFormat(source) {}
      2. function hear(theBells) {}
    • 类, 使用帕斯卡命名法

    • 类的 方法 / 属性, 使用驼峰命名法

      1. function TextNode(value, engine) {
      2. this.value = value;
      3. this.engine = engine;
      4. }
      5. TextNode.prototype.clone = function () {
      6. return this;
      7. };
    • 枚举变量 使用帕斯卡命名法。

    • 枚举的属性, 使用全部字母大写,单词间下划线分隔的命名方式。

      1. var TargetState = {
      2. READING: 1,
      3. READED: 2,
      4. APPLIED: 3,
      5. READY: 4
      6. };
    • 由多个单词组成的 缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。

      1. function XMLParser() {}
      2. function insertHTML(element, html) {}
      3. var httpRequest = new HTTPRequest();
    • 命名语法

      • 类名,使用名词

        1. function Engine(options) {}
      • 函数名,使用动宾短语

        1. function getStyle(element) {}
      • boolean 类型的变量使用 is 或 has 开头

        1. var isReady = false;
        2. var hasMoreCommands = false;
      • 获取的 DOM 元素变量 使用 e 或 el 开头

      • 模块初始化时,可直接使用模块名称作为初始化的变量名,主要是方便直接copy官方的示例代码

    3.3.2. 注释

    注释是程序开发人员和程序阅读者之间交流的手段,对代码的解释和说明,提高软件的可读性,有利于程序应用的维护。

    • 对象、方法、逻辑分支以及代码块的上行应有完整名称及其用途的注释, 但应避免对代码过于详细的描述

      • As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性、可读性
      • As long as necessary(如有必要,尽量详尽):合理的注释、空行排版等,可以让代码更易阅读、更具美感

        1. 正确示例:
        2. // 将距离单位转换为公里
        3. function fnDistanceParse(distance){
        4. return 1000 <= distance ? parseInt(distance / 1000 * 100) / 100 : distance; };
        5. 错误示例:
        6. // 利用根据标准利用 parseInt 将距离单位转换为公里
        7. function fnDistanceParse(distance){
        8. return 1000 <= distance ? parseInt(distance / 1000 * 100) / 100 : distance; };
    • 一致重要变量须有注释,注释写在变量之后,应解释变量的含义及用途

    • 典型算法须有注释

    • 单行注释

      • 必须独占一行
      • 每行注释的最大长度为 100 个字符
      • //”(注释符号)与注释文字之间须使用一个空格分隔开
    • 多行注释

      • 有多行注释内容时,建议使用多个单行注释
    • 函数注释

      • 无参函数或简单类型形参函数可采用单行注释方式进行注释
      • 多参函数或对象类型形参函数须采用一下标准函数注释方法

        • 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识
        • 参数和返回值注释必须包含类型信息和说明

          1. 例如
          2. /**
          3. * 函数的描述
          4. *
          5. * @param {String} p1 参数1的说明
          6. * @param {Number} p2 参数2的说明,比较长
          7. * 那就换行了.
          8. * @param {Boolen} p3 参数3的说明(可选)
          9. * @return {Boolen} 返回值描述
          10. */
          11. function fnMethod(p1, p2, p3) {
          12. var tFlag = false;
          13. /*
          14. 代码逻辑省略
          15. */
          16. }
    • JavaScript文件注释

      文件注释用于说明当前文件中主体结构和主要用途。

    • 【必须】在代码交付之前,须删掉临时的或多余的注释

    • 【必须】代码中不要存在任何的第三方信息,如开发者的相关信息、开发公司的相关信息等

    返回目录