UNPKG

sumeru

Version:

A Realtime Javascript RIA Framework For Mobile WebApp

2,416 lines (1,420 loc) 53.6 kB
# API 文档 ##Router 用于建立URL(其路径部分)和Controller的对应关系,一个Controller可以对应多个URL,但是一个URL只能对应一个Controller。 * ### add 语法:add({pattren:'', action:''}) 在router中添加一组pattren与Controller的对于关系 sumeru.router.add( { pattern: '/studentList', action: 'App.studentList' } ); * pattern URL(其路径部分的值) * action 对应Controller的名称 如果你想**关闭Server渲染**,可使用下面方法: sumeru.router.add( { pattern: '/studentList', action: 'App.studentList' server_render:false } ) * server_render Server渲染开关,false:关闭,默认为开启 * ### setDefault 语法:setDefault(controllerName) 设置默认启动Controller sumeru.router.setDefault('App.studentList'); * ### externalProcessor.add(processor); 语法:sumeru.router.externalProcessor.add(processor); 添加外部处理器 添加一个backbone的外部处理器 sumeru.router.externalProcessor.add(Backbone.Router.extend()); ## Model Model用来定义App的数据模型。 Model.student = function(exports){ exports.config = { fields: [ {name : 'studentName', type: 'string'}, {name : 'age', type: 'int'}, {name : 'gender', type: 'string'} ] }; }; ##### 属性 * ##### name 字段的名称 * ##### type 字段的数据类型,包括一下数据类型: <table border="0" cellpadding="0" cellspacing="0" style="margin-left: 30px;" > <tr style="background-color:#3982ff"> <th>类型</th> <th>意义</th> </tr> <tr> <th>int</th> <th>整形</th> </tr> <tr> <th>datetime</th> <th>日期</th> </tr> <tr> <th>string</th> <th>字符串数</th> </tr> <tr> <th>object</th> <th>对象</th> </tr> <tr> <th>array</th> <th>数组</th> </tr> <tr> <th>model</th> <th>数据模型</th> </tr> <tr> <th>collection</th> <th>数据集合</th> </tr> </table> * ### relation 使用relation时type属性值必须为“model”。 {name: 'class', type: 'model', relation: 'one' , model:'Model.class'}, * one 引用一个Model * many 引入一个Collection * ### defaultValue 字段的默认值 {name: 'gender', type: 'string', defaultValue:'male'}, * ### validation {name: 'name', type: 'string', validation:'length[1,20]'}, 字段的验证,validation包括以下方法: <table border="0" cellpadding="0" cellspacing="0" style="margin-left: 30px;"> <tr style="background-color:#3982ff"> <th>方法</th> <th>意义</th> </tr> <tr> <th>length[min,max] </th> <th> 字段值的长度在min-max的范围。</th> </tr> <tr> <th>minlength(min)</th> <th>字段值不小于min</th> </tr> <tr> <th>maxlength(min)</th> <th>字段值不大于min</th> </tr> <tr> <th>required</th> <th>字段值不能为空</th> </tr> <tr> <th>unique</th> <th>字段值必须唯一</th> </tr> <tr> <th>telephone</th> <th>字段值必须为电话号码格式</th> </tr> <tr> <th>mobilephone</th> <th>字段值必须为手机号码格式,长度为11位且必须为数字</th> </tr> <tr> <th>email</th> <th> 字段值必须为email格式</th> </tr> <tr> <th>onlyletter</th> <th>字段值必须是字母</th> </tr> <tr> <th>nospecialchars</th> <th>字段值不能包含特殊字符</th> </tr> <tr> <th>date</th> <th>字段值必须是日期格式</th> </tr> <tr> <th>url</th> <th>字段值必须是URL</th> </tr> <tr> <th>chinese</th> <th>字段值必须是中文</th> </tr> </table> 注:多个验证条件之间使用" | "连接 {name: 'name', type: 'string', validation:'length[1,20]|required'}, * ### addRule 除了上面的验证方法外,还可以自定义验证方法。 sumeru.validation.addRule(ruleName,{ "runat" : "client", 验证方法 , "msg" : "", }); * ruleName 验证方法的名称,如"chinese""url" * runat 定义在哪个端上(client/server)进行验证 * client 在客户端上进行验证 * server 在服务器端进行验证 * both 两段都需要验证 * 验证方法:该API中框架提供三种自定义验证方法(**三种方法(regxp/func/asyncFunc)每次只能使用一种**) * regxp 使用自定义正则表达式对字段进行验证 sumeru.validation.addRule(ruleName,{ "runat" : "client", "regxp" : "()", "msg" : "", }); * func 使用自定义函数对字段进行验证 sumeru.validation.addRule(ruleName,{ "runat" : "client", "func" : function(){}, "msg" : "", }); * asyncFunc 该验证函数在服务器端运行,先获取指定modelObj的数据,然后根据asyncFunc中的方法进行验证,在callback中给出验证的结果。 sumeru.validation.addRule(ruleName,{ "runat" : "client", "asyncFunc":function(callback,k,v,modelObj){} "msg" : "", }); * msg 验证失败后返回的信息 * ### create 语法:create(modelName) 创建一个model var newStudent = sumeru.model.create('Model.student') * ### setter newStudent.studentName = 'John'; * ### set 语法:set(key,value) 设置Model中相应字段的值 newStudent.set('studentName','John'); * ### setData 语法:setData(dataMap) 使用dataMap对Model赋值 newStudent.setData({'studnetName' : 'Smith', 'age' : 19, 'gender' : 'male' }); * ### getter var name = newStudent.studentName; * ### get 语法:get(key) 获取某一字段的值 newStudent.get('studentName'); * ### getId 语法:getId() 获取model的唯一Id newStudent.getId(); * ### getData 语法:getData() 返回一个JSON数据对象 newStudent.getData(); * ### destroy 语法:destroy() 删除model newStudent.destroy(); * ### onValidation 语法:onValidation(ispass, runat, validationResult) 对Model验证结果的监听方法 * ispass 验证是否通过的标志 * true 验证通过 * false 验证不通过 * runat 返回进行验证的端(客户端或者服务器端) * client 表示在客户端进行验证 * server 表示在服务器端进行验证 * validationResult 验证返回信息 newStudent.onValidation = function(ispass, runat, validationResult){ if(ispass){console.log("Validation success !");} console.log((runat=='client'?'Client':'Server')+(ispass==true?'Validation Success!':'Validation failed!')); for(var i = validationResult.length-1; i>=0; i--){ console.log(runat=='client'?'Client':'Server')+'result is:'+validationResult[i].msg); } }; 详细代码和说明请参考《Examples》文档。 ## Collection Collection是Model的集合,我们之前曾使用过的subscribe()返回的结果集即是Collection。 session.studentCollection = env.subscribe("pub-allStudents",function(myCollection){ }); * ### create 语法:create(dataMap) 创建一个Collection sumeru.collection.create({'studnetName' : 'Smith', 'age' : 19, 'gender' : 'male' }); * ### size 语法:size() 获取collection中包含Model的数量。 session.studentCollection.size(); * ### add 语法:add(row) 在collection中添加一行数据(每行数据实际是一个Model)。 session.studentCollection.add(newStudent); * ### update 语法:update(updateMap,where) 更新collection中满足条件的数据。 session.studentCollection.update({'name':'Jack'},{'name':'John'}); * ### remove 语法:remove(where) 将数据从collection中去除,但并不实际删除。 session.studentCollection.remove({'name':'John'}); 当没有参数时,去除collection中所有数据。 * ### destroy 语法:destroy(where) 将数据从collection中实际删除。 session.studentCollection.destroy({'name':'John'}); 当没有参数时,删除collection中所有数据。 * ### setData 语法:setData(dataMap) 使用dataMap对Model赋值 * ### find 语法:find(where) 查询Collection中符合条件的所有数据。 session.studentCollection.find({'name':'John'}); 当没有参数时,返回所有的数据。 * ### addSorters 语法:addSorters() collection中添加排序方法 session.studentCollection.addSorters('time','DESC') collection按照"time"降序排序。 * ### clearSorters 语法:clearSorters() 清空collection中排序方法 session.studentCollection.clearSorters(); * ### applyStorters 语法:applyStorters() 手动执行所有的排序方法 session.studentCollection.applyStorters(); * ### get 语法:get() 根据下标取出对应的数据 session.studentCollection.get(2); * ### toJSON 语法:toJSON() 返回一个JSON对象 session.studentCollection.toJSON(); * ### getData 语法:getData() 获取包含所有数据的数组 session.studentCollection.getData(); * ### save 语法:save() 将collection的修改保存到Server。 session.studentCollection.save(); * ### pluck 语法:pluck(key) 返回Collection某一字段所有数据的数组 session.studentCollection.pluck('age'); * ### hold 语法:hold() 暂停collection实时更新 session.studentCollection.hold(); * ### releaseHold 语法:releaseHold() 恢复对collection的实时更新 session.studentCollection.releaseHold(); * ### where 语法:where() 在collection中指定查询条件,需要与find、update、remove、destroy连用。 session.studentCollection.where({'gender':'male'}); session.studentCollection.find(); 返回collection中‘gender’值为‘male’数据的数组。 * ### orWhere 语法:orWhere() 在collection中添加一个“or”条件,需要与find、update、remove、destroy连用。 session.studentCollection.orWhere({'gender':'male'}); session.studentCollection.find(); * ### clearWheres 语法:clearWheres() 清空collection中所有查询条件 session.studentCollection.clearWheres() ## View View使用handlebars组件作为模板引擎,handlebars语法请参考官网。 为了更快的开发视图代码,Clouda对handlebars的语法做了一些扩展: * ### view中引入view 语法: {{> viewName}} 在一个View中引用另一个View。 * ### view中使用JS 语法: {{$ alert("data.length"); }} 在View中直接执行Javascript代码,并将返回结果输出在View中。 * ### foreach 用于快速遍历一个对象或数组 语法:{{#foreach}}{{/foreach}} 用法示例: <p id="test-foreach-caseB"> {{#foreach customObj}} {{key}} : {{value}} {{/foreach}} </p> * ### compare 比较两个对象 语法: {{#compare a operator b}} {{else}} {{/compare}} 可以使用的operator: <table border="0" cellpadding="0" cellspacing="0" style="margin-left: 30px;" > <tr style="background-color:#3982ff"> <th> operator </th> </tr> <tr> <th> == </th> </tr> <tr> <th> ===</th> </tr> <tr> <th> != </th> </tr> <tr> <th> !== </th> </tr> <tr> <th> < </th> </tr> <tr> <th> <= </th> </tr> <tr> <th> > </th> </tr> <tr> <th> >= </th> </tr> <tr> <th> typeof </th> </tr> </table> 用法示例: {{#compare a "<" b}} a < b {{else}} a >= b {{/compare}} {{#compare a "typeof" "undefined"}} undefined {{/compare}} **注意**:当省略operator时,系统默认使用操作符 ==: {{#compare 1 1}} 1 == 1 {{/compare}} * ### sumeru.config.view.set 语法:sumeru.config.view.set('path', viewpath); 一般情况下将编写的view文件存放在app/view文件夹下,如果编写的view文件不在View文件夹下,我们也提供View文件路径配置的方法,框架会在配置路径下寻找需要的View文件: 实例: sumeru.config.view.set('path', 'path/to/'); 则Clouda会在如下目录中加载视图: app目录/path/to/view/ 注意:即使是修改viewpath的情况下,**在最内一侧仍然需要有一层view文件夹**,如上面路径的最后部分。 ## Transition 当场景发生转换时,通过transition定义场景转换效果。 doRender(viewName,transition) * viewName 需要渲染View的名称 * transition * ### push 推出 * 方向 * left 从左向右推出 * right 从右向左推出 * up 从上向下推出 * down 从下向上推出 * ### rotate 旋转 * 方向 * left * right * ### fade 渐变 * 方向 * z-index 垂直方向 * ### shake 退出场景时先缩小后放大退出,进入场景从左或者右边推入 * 方向 * left 从左推入进场 * right 从右推入进场 * ### none 没有转场效果 * 方向参数 * z 默认参数 实例: env.onrender = function(doRender){ doRender('student', ['push', 'down']); }; env.onrender = function(doRender){ doRender('student', ['none', 'z']); }; ## Controller 如果你曾经接触过MVC模型,那么将会很熟悉Controller的概念。在Clouda中,Controller是每个场景的控制器,负责实现App的核心业务逻辑。 * ### create 语法:sumeru.controller.create(function(env,session){}); 创建一个Controller App.studentList = sumeru.controller.create(function(env,session){}); * ### env * #### redirect 语法:env.redirect(queryPath,paramMap,isforce) 一个Controller跳转到另一个Controller env.redirect('/studentList',{'class':'101'}); * queryPath router中pattern的值 * paramMap 需要向跳转Controller传递的参数 * isforce 是否强制生成一个全新的Controller实例。 如果在redirect中使用paramMap,可以在跳转目标Controller的create()中"param"接受参数。 App.studentList = sumeru.controller.create(function(evn,session,param){ }); * #### refresh 语法: env.refresh() 重新加载当前Controller env.refresh(); * #### onload 语法:env.load() onload()是Controller的第一个时态,Controller中需要使用的数据都在这个时态中加载。 env.onload = function(){ return [ ]; }; * #### onrender 语法:env.onrender() 当数据获取完成后,这些数据需要显示在视图(View)上,这个过程通过onrender()中的代码来实现,这是Controller的第二个时态,负责完成对视图(View)的渲染和指定转场方式。 env.onrender = function(doRender){ doRender(viewName,transition); }; * #### onready 语法:onready() 这是Controller的第三个时态,在View渲染完成后,事件绑定、DOM操作等业务逻辑都在该时态中完成;每段逻辑使用session.event包装,从而建立事件与视图block的对应关系。 env.onready = function(){ session.event(blockID,function(){ }); }; * #### onsleep 语法:env.onsleep() 当Controller长时间不处于活动状态时,可能会被置为睡眠状态,以确保正在运行中的Controller具有足够的资源。如果需要在Controller被暂停之前运行一些逻辑(比如暂存状态等),可以在onsleep()中完成。 env.onsleep = function(){ }; * #### onresume 语法:env.onresume() 当处在睡眠状态的Controller被唤醒时,onresume()时态将被调用。该时态可用于执行一些恢复性业务逻辑 env.onresume = function(){ }; * #### ondestroy 语法:env.ondestroy 当Controller被销毁时,ondestroy()将被调用。 env.ondestroy = function(){ }; * #### onerror 语法: env.onerror 当前Controller收到错误消息时被触发 env.onerror = function(){ }; * ### subscribe 语法: 不带参数: env.subscribe(publishName, function(collection){}); 带参数: env.subscribe(publishName,arg1,arg2, ... , function(collection){}); 关于subscribe方法请查看“Publish/Subscribe”章节。 * ### session * #### set 语法:session.set(key,value) 在session中设置“key”的值 session.set('page',10); * #### get 语法:session.get(key) 获取session中“key”的值 session.get('page'); * #### bind 语法:session.bind(block-id,dataMap) 将数据绑定到视图中block-id容器 session.bind('student-list',{ data : Collection.find() }); 一般在subscribe(publishName,function(Collection){})的function(Collection){}中使用。 * #### event 语法:seesion.event(block-id,function(){}) 建立事件与视图block的对应关系 session.event('student-list'function(){ var submitButton = document.getElementById('submit'); submitButton.addEventListener('click', submitMessage); }); * #### eventMap 语法:session.eventMap(id,eventMap) 对一个标签绑定多个事件 session.eventMap('inputMessage',{ 'focus':function(e){ console.log('focus!'); }, 'blur':function(e){ console.log('blur'); }, }); * id View中标签ID * eventMap 事件Map * #### commit 语法:session.commit() 触发数据对应视图block的更新 session.commit(); ### sub controller 创建的Controller可以作为另外一个Controller的子Controller使用。 * #### callSubController 语法: callSubController(queryPath,options) 在当前Controller中调用一个子Controller,配合show()和hide()方法使用。 * #### isready 语法:env.isready(){} 当前Controller的子Controller已经加载完成 env.isready = function(){ }; * #### show 语法:env.show(){} 显示当前当前Controller的子Controller env.show = function(){ }; * #### hide 语法:env.hide(){} 隐藏当前Controller的子Controller env.hide = function(){ }; * #### destory 语法:env.destory(){} 销毁当前Controller的子Controller env.destroy = function(){ }; ## Touch 在开发移动端的应用中会使用到很多的手势操作,例如一指拖动、两指旋转等等,为了方便开放者快速集成这些手势,在Clouda中内置了事件和手势库`Library.touch`,下面将详细的介绍如何使用Library.touch### touch.config 语法: touch.config(config) 对手势事件库进行全局配置。 参数描述: * config为一个对象 { tap: true, //tap类事件开关, 默认为true doubleTap: true, //doubleTap事件开关, 默认为true hold: true, //hold事件开关, 默认为true holdTime: 650, //hold时间长度 swipe: true, //swipe事件开关 swipeTime: 300, //触发swipe事件的最大时长 swipeMinDistance: 18, //swipe移动最小距离 swipeFactor: 5, //加速因子, 值越大变化速率越快 drag: true, //drag事件开关 pinch: true, //pinch类事件开关 } ### touch.on 语法:touch.on(element, types, options, callback) 绑定指定元素的事件。 参数描述: * element: 元素对象或选择器。 * types: 事件的类型, 可接受多个事件以空格分开,支持原生事件的透传, 支持的一些事件类型有: <table border="0" cellpadding="0" cellspacing="0" style="margin-left: 30px;" > <tr> <th> pinchstart </th> <th> 双指缩放动作开始 </th> </tr> <tr> <th> pinchend </th> <th> 双指缩放动作结束 </th> </tr> <tr> <th> pinch </th> <th> 双指缩放事件 </th> </tr> <tr> <th> pinchin </th> <th> 双指向里缩小 </th> </tr> <tr> <th> pinchout </th> <th> 双指向外放大 </th> </tr> <tr> <th> rotateleft </th> <th> 向左旋转 </th> </tr> <tr> <th> rotateright </th> <th> 向右旋转 </th> </tr> <tr> <th> rotate </th> <th> 旋转事件 </th> </tr> <tr> <th> swipestart </th> <th> 单指滑动动作开始 </th> </tr> <tr> <th> swiping </th> <th> 单指滑动事件 </th> </tr> <tr> <th> swipeend </th> <th> 单指滑动动作结束 </th> </tr> <tr> <th> swipeleft </th> <th> 单指向左滑动 </th> </tr> <tr> <th> swiperight </th> <th> 单指向右滑动事件 </th> </tr> <tr> <th> swipeup </th> <th> 单指向上滑动 </th> </tr> <tr> <th> swipedown </th> <th> 单指向下滑动 </th> </tr> <tr> <th> swipe </th> <th> 单指滑动事件 </th> </tr> <tr> <th> drag </th> <th> 单指向左右拖动 </th> </tr> <tr> <th> hold </th> <th> 单指按住不放事件 </th> </tr> <tr> <th> tap </th> <th> 单指点击 </th> </tr> <tr> <th> doubletap </th> <th> 单指双击 </th> </tr> </table> 例如旋转实例如下: var angle = 30; touch.on('#rotation .target', 'touchstart', function(ev){ ev.startRotate(); ev.originEvent.preventDefault(); ev.originEvent.stopPropagation(); }); touch.on('#rotation .target', 'rotate', {interval: 10}, function(ev){ var totalAngle = angle + ev.rotation; if(ev.fingerStatus === 'end'){ angle = angle + ev.rotation; } this.style.webkitTransform = 'rotate(' + totalAngle + 'deg)'; }); 更多使用实例请查看<http://code.baidu.com/> * options(可选): 目前可配置的参数为: { //采样频率 interval: 10,//性能参数,值越小,实时性越好, 但性能可能略差, 值越大, 性能越好。遇到性能问题时,可以将值设大调优,建议值设置为10。 //swipe加速度因子(swipe事件专用) swipeFactor: 5 //(int: 1-10)值越大,速率更快。 } * callback: 事件处理函数, 该函数接受的参数为一个gesture event object, 可访问的属性有: * originEvent //触发某事件的原生对象 * type //事件的名称 * rotation //旋转角度 * scale //缩放比例 * direction //操作的方向属性 * fingersCount //操作的手势数量 * position //相关位置信息, 不同的操作产生不同的位置信息。 * distance //swipe类两点之间的位移 * distanceX //swipe类事件x方向的位移 * distanceY //swipe类事件y方向的位移 * angle //swipe类事件触发时偏移角度 * factor //swipe事件加速度因子 * startRotate //启动单指旋转方法,在某个元素的touchstart触发时调用。 ### touch.live 语法:touch.live(selector, types, options, callback) 使用方法基本上与on相同,live的第一个参数只接受`css3选择器`。通过`live()`方法附加的事件处理程序适用于匹配选择器的当前及未来的元素(比如由脚本创建的新元素) ### touch.off 语法:touch.off(element,types,callback) 解除某元素上的事件绑定。 参数描述: * element:元素对象或选择器 * types:事件的类型 * callback:时间处理函数 ## Publish/Subscribe ### subscribe 订阅被发布的数据,与pubilsh配合使用 * 不带参数 env.subscribe(publishName, function(collection){}); env.subscribe("pub-allStudents", function(studentCollection){ }); * pulishName 所定义的Publish的唯一名称,在一个App内全局唯一,该参数与sumeru.publish(modelName, publishName,function(callback))中的publishName名称需要保持一致。 * function(Collection){} Subscribe成功获得数据时,被调用的响应方法。 * 带参数 env.subscribe(publishName,arg1,arg2, ... , function(collection){}); env.subscribe("pub-StudentsWithGender", "male", function(msgCollection){ }); * #### subscribeByPage 分页订阅数据 * 不带参数 env.subscribeByPage(publishName, options, function(collection){}); var pageOption{ pagesize : 1, page : 2, uniqueField : 'time' }; env.subscribeByPage("pub-allStudents", pageOption, function(studentCollection){ }); * options 分页设置 * pageSize 每页数据的数量 * page 页码 * uniqueField 排序的唯一字段名 * 带参数 env.subscribeByPage(publishName, options, arg1,arg2, ... , function(collection){}); env.subscribeByPage("pub-StudentsWithGender", pageOption, "male", function(msgCollection){ }); * #### prioritySubscribe 在断线重新连接的情况下,使用prioritySubscribe方法订阅数据优先被调用,使用方式与subscribe相同。 ### publish 发布数据的方法,其运行在Server上。 * 不带参数 sumeru.publish(modelName,pubName,function(callback){},options) * modelName 被发布数据所属的Model名称 * pubName 所定义的Publish的唯一名称,在一个App内全局唯一,该参数与Controller中subscribe()成对使用。 * function(callback) 描述数据发布规则的自定义函数,在这里定义被发布数据所需要符合的条件。 * options 可在此添加以下六种事件 * beforeInsert 在实际插入数据到数据库前的事件 beforeInsert : function(serverCollection, structData, userinfo, callback){ callback(structData); } * structData 需要插入到数据库的数据,我们可以对该数据进行操作,然后将数据插入到数据库中,如果对数据没有修改,则将原数据添加到数据库中。 * callback before系列的事件中如果不添加 callback(),将阻止数据对数据库的影响。 * callback(structData) 如果需要对原数据进行修改,可以传入参数structData * afterInsert 在实际插入数据到数据库后的事件 afterInsert : function(serverCollection, structData){ } * beforeUpdate 在实际更新数据库数据前的事件 beforeUpdate : function(serverCollection, structData, userinfo, callback){ callback(); } * afterUpdate 在实际更新数据库数据后的事件 afterUpdate : function(serverCollection, structData){ } * beforeDelete 在实际删除数据库数据前的事件 beforeDelete : function(serverCollection, structData, userinfo, callback){ callback(); } * afterDelete 在实际删除数据库数据后的事件 afterDelete : function(serverCollection, structData){ } 实例: module.exports = function(sumeru){ sumeru.publish('student', 'pub-allStudents', function(callback){ var collection = this; collection.find({}, function(err, items){ callback(items); }); }); } * 带参数 sumeru.publish(modelName,pubName,function(arg1, ..., callback){},options) 实例: module.exports = function(sumeru){ sumeru.publish('student', 'pub-allStudents', function(gender,callback){ var collection = this; collection.find({'gender':gender}, function(err, items){ callback(items); }); }); } * #### publishByPage 分页发布数据 sumeru.publishByPage(modelName,pubName,function(arg1,arg2,...,pageOptions, callback){},options) * options 分页设置,有Controller中subscribeByPage()传入。 实例: sumeru.publishByPage('student', 'pub-allStudents', function(gender,options,callback){ var collection = this; collection.find({ sort :{'time':-1}, limit : options.pagesize, skip : (options.page-1)*options.pagesize, "gender": gender }, function(err, items){ callback(items); }); }); * sort 排序 * limit 每页显示的个数 * skip 当前页与起始页间隔的个数 详细的使用情况请查看《Example》文档中的实例。 * #### publishPlain 用于发布简单对象,而非Collection。 sumeru.publishPlain(modelName,pubName,function(callback){},options) 实例: 如果需要发布Collection中数据的总数量,可使用下面方法: fw.publishPlain('student', 'pub-allStudents', function(callback){ var collection = this; collection.count({},function(err, count){ callback(count); }); }); 下面的三种方法是包含权限中心的身份验证的Publish。 * #### securePublish 在身份验证成功的情况下发布数据 sumeru.publish(modelName,pubName,function(userinfo, callback){},options) * #### securePublishByPage 在身份验证成功的情况下分页发布数据 sumeru.securePublishByPage(modelName,pubName,function(pageOptions,userinfo, callback){},options) * #### securePublishPlain 在身份验证成功的情况下发布简单对象 sumeru.securePublishPlain(modelName,pubName,function(userinfo, callback){},options) * #### external 实现了三方数据同步的方法,用来满足从三方网站/三方接口获取和同步数据的需求。 * extfind(pubName,callback) 在publish文件中发布第三方数据 fw.publish('news','pubnews',function(callback){ var collection = this; collection.extfind('pubnews',callback); }); 使用该方法需要在publish下添加一个如何获取第三方数据的配置文件 * config[pubname] * pubname 与publish中collection.extfind(pubname,callback)方法pubname一致,全局唯一 * uniqueColumn uniqueColumn为三方数据唯一标识,类型为`String` uniqueColumn : "name", * fetchUrl: function((/** arg1, arg2, arg3 */)){} 指定抓取的URL。arg1,arg2为传递的参数 fetchUrl : function(/** arg1, arg2, arg3 */){ return 'http://some.host.com'; } * resolve : function(originData){} resolve方法作用是将抓取回来的原始数据(originData)转化成为符合Model定义的数据(resolved) resolve : function(originData){ var j = JSON.parse(originData); var resolved = j; return resolved; } * fetchInterval fetchInterval为可选参数,用来指定抓取时间间隔,单位为ms * buffer buffer为可选参数,值为true时表示获取原始Buffer,否则获取原始数据字符串 * type 声明此模块为归属为'external' return { type : 'external', config : config } 实例如下: /** * 获取三方数据信息,由开发者自定义 */ function runnable(){ //{Object} config是所有三方publish配置的容器 var config = {}; config['pubext'] = { //{String} uniqueColumn为三方数据唯一标识 uniqueColumn : "name", //{Function} fetchUrl的参数就是订阅时发起的参数,返回值为pubext所抓取的url地址 fetchUrl : function(/** arg1, arg2, arg3 */){ return 'http://some.host.com'; }, //{Function} resolve方法作用是将抓取回来的原始数据(originData)转化成为符合Model定义的数据(resolved) resolve : function(originData){ var j = JSON.parse(originData); var resolved = j; return resolved; }, //{Number} fetchInterval为可选参数,用来指定抓取时间间隔,单位为ms fetchInterval : 60 * 1000, //{Boolean} buffer为可选参数,值为true时表示获取原始Buffer,否则获取原始数据字符串 buffer : false } //最后需要声明此模块为归属为'external' return { type : 'external', config : config } } module.exports = runnable; * 指定三方增/删/改接口以及数据 当数据发生变化时,如何使用Clouda达到三方数据同步的效果,具体实现方法如下: * 较为紧凑的声明方式 * postUrl `postUrl`方法用来指定三方post接口的地址信息, 参数type为增量类型,增量类型为'insert','update','delete'三者之一; * prepare `prepare`方法用来将增量数据转化成为符合三方POST接口要求的post数据,参数type同为增量类型,参数data为增量的实际数据。 实例如下: /** * 三方数据POST请求信息,由开发者自定义 */ function runnable(){ var config = {} config['pubext'] = { /** * 声明三方POST接口地址 * {String} type'delete', 'insert', 'update'其中之一 * 如果subscribe时带参数,参数会按照subscribe顺序接在postUrl的参数中 */ postUrl : function(type /** arg1, arg2, arg3... */){ var options = { host : 'some.host.com', path : '/' + type , headers: { //在此自定义header内容,clouda默认的 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': ... } } return options; }, /** * prepare方法将增量数据转化为符合三方要求的post数据。 * {String} type为增量操作,值为'delete', 'insert', 'update'其一; * {Object} data为增量数据,如:{ name : 'user1', age : 26 }。 */ prepare : function(type, data){ var prepareData = {}; //prepareData为三方post所需的data if(type === "delete"){ prepareData.name = data.name; }else if(type === "insert"){ prepareData.name = data.name; prepareData.age = data.age; }else{ prepareData.name = data.name; prepareData.age = data.age; } return prepareData; } } return { type : 'external', config : config } } module.exports = runnable; * 较为工整的声明方式 * `deleteUrl`,`insertUrl`,`updateUrl` 三个方法作用等同于`postUrl`,返回不同操作下三方接口url信息 * `onDelete`,`onInsert`,`onUpdate` 三个方法作用等同于`prepare`方法, 返回经过处理,传给三方接口的post数据 实例如下: function runnable(){ var config = {}; config['pubext'] = { //arg1, arg2, arg3是subscribe时输入的参数 deleteUrl : function(/** arg1, arg2, arg3... */){ return { host : 'some.host.com', path : '/delete' } }, insertUrl : function(/** arg1, arg2, arg3... */){ return { host : 'some.host.com', path : '/insert' } }, updateUrl : function(/** arg1, arg2, arg3... */){ return { host : 'some.host.com', path : '/update' } }, onInsert : function(data){ var prepareData = {}; prepareData.name = data.name; prepareData.age = data.age; return prepareData; }, onUpdate : function(data){ var prepareData = {}; prepareData.name = data.name; prepareData.age = data.age; return prepareData; }, onDelete : function(data){ var prepareData = {} prepareData.name = data.name; return prepareData; } } return { type : 'external', config : config } } module.exports = runnable; * sumeru.external.get 向第三方发送get请求 var url = "http://some.host.com"; var getCallback = function(data){ console.log(data); } sumeru.external.get(url, getCallback); * sumeru.external.post 向第三方发送post请求 var options = { host : "some.host.com", path : "/insert" } var postData = { name : sumeru.utils.randomStr(8), age : parseInt( 100 * Math.random()) } var postCallback = function(data){ console.log(data); } sumeru.external.post(options, postData, postCallback); * sumeru.external.sync 将抓取最新的三方数据,并将新数据推送至前端 var cb = function(data){ console.log(data); } var url = "some.host.com"; sumeru.external.sync(modelName, pubName, url, cb); 具体使用请查看《Example》文档中的SpiderNews实例。 ## Auth * ### create 创建一个auth对象 sumeru.auth.create(env) 实例: var myAuth = sumeru.auth.create(env); ### Auth对象的方法 * ### on 增加一个用户系统相关的事件监听器 on(type,handle); 参数说明: * type 每次认证状态变化时被触发,类型string,目前只支持一个事件类型,即 “statusChange” * handle 事件处理函数. 可接收两个参数`err`与`status` * err 有错误产生时的错误对像 * status 表示当前认证状态的字符串 * not_login 当前未登陆 * logined 已登陆 * doing_login 正在登陆过程中 实例: var myAuth = sumeru.auth.create(env); var statusChangeHandle = function(err,status){ if(err){ // err.code | err.msg return; }; switch(status){ case "not_login" : // do something break; case "logined" : // do something break; case "doing_login" : // do something break; default: // do something } } myAuth.on('statusChange',statusChangeHandle); * ### removeListener 移除由on方法增加的监听器 removeListener(type,handle) 参数说明: * type 事件名称, 目前只支持一个事件,即“statusChange” * handle 事件处理函数 * ### removeAllListener 一次性移除所有已添加的监听器事件 removeAllListener(type) 参数说明: * type 事件名称, 目前只支持一个事件,即“statusChange” 实例: var myAuth = sumeru.auth.create(env); myAuth.removeAllListener('statusChange'); * ### login 根据token,pwd登陆由`authMethod`所指定的类型用户系统. 不提供`authMethod`时默认为`local`. 登陆过程中的每次状态变化将触发`statusChange`事件 login(token,pwd,[args],[authMethod]) 参数说明: * token 用户的用户名,类型为string * pwd 用户的密码,类型为string * args 登陆时需附加的其它信息,具体内容根据`authMethod`的不同传入内容将不同.如不提供默认为{},类型为map,所有除用户名和密码外需要传入的其它数据(如验证码等),都需要通过这个args参数传入 * authMethod 登陆用户的类型,默认为“local”,类型为string 实例: var myAuth = sumeru.auth.create(env); var statusChangeHandle = function(err,status){ if(err){ // err.code | err.msg return; }; switch(status){ case "not_login" : // do something break; case "logined" : // do something break; case "doing_login" : // do something break; default: // do something } } myAuth.on('statusChange',statusChangeHandle); // 完整的调用方式 myAuth.login('userName','pwd',{a:100,b:200,c:[1,2,3]},'authMehtod_XXX'); // 也可使用以下不完整的参数调用方式。 // 1.省略authMethod认为 authMethod = 'local' // myAuth.login('userName',’pwd‘,{a:100,b:200}); // 2.同时省略args与authMethod时,认为args={},authMethod='local' // myAuth.login('userName','pwd'); * ### logout 登出,并触发statusChange变化 logout() 实例: var myAuth = sumeru.auth.create(env); myAuth.logout(); * ### getStatus 取得当前的认证状态. 返回值为String类型 getStatus() 返回值如下: * not_login 当前未登陆 * logined 已登陆 * doing_login 正在登陆过程中 实例: var myAuth = sumeru.auth.create(env); myAuth.getStatus(); * ### getLastError 取得最后一个操作发生的错误信息,每一个新操作产生时,上一次的错误信息将被清空 getLastError() 实例: var myAuth = sumeru.auth.create(env); var errObj = myAuth.getLastError(); console.log(errObj); * ### getUserInfo 取得当前认证用户的信息,如果未登陆则返回`null` getUserInfo() 实例: var myAuth = sumeru.auth.create(env); myAuth.getUserInfo(); userInfo结构如下: userInfo = { "token":"token", "info":{"param1":"modify1","param2":"modify2","param3":["1","2"]}, "status":"online", "smr_id":"5253a5aa546610001200014a", "__clientId":"7qgj3s1grr", "userId":"5253a5a95466100012000148", "clientId":"183ou3qrg_QZKUYDxapKFO", "authMethod":"local", "expires":1381213910081 } 注意:其中info字段的内容,来源于`register`时提供的userInfo * ### register 注册一个用户 register(token,pwd,userInfo, authMethod, callback) 参数说明: * token 用户的登陆标识,类型为string * pwd 登陆密码,类型为string * userInfo 新的用户信息对像,类型为object * authMethod 目标的用户类型,类型为string * callback 注册完成后的回调方法,可接收一个`err`参数,当产生错误时返回对应的错误对像,如果成功,返回`null` 实例: var myAuth = sumeru.auth.create(env); myAuth.register('user123','pwd',{age:100},local,function(err){ if(err){ // 注册失败 return; } // 注册成功 // do something .. }); 注意:在注册前,尽量使用sumeru.auth.registerValidate() 进行验证,可以有效减少错误发生。 * ### registerValidate 测试一个注册信息是否可用 registerValidate(userInfo,authMethod,callback) 参数说明: * userInfo 待测试的注册信息,类型为object * authMethod 用户类型,类型为string * callback 测试完成后的回调函数,可接收err与isUsefull参数 * err 产生错误是传入对应的错误对像 * isUserfull 值为`true`时表示测试的用户可以使用 实例: var myAuth = sumeru.auth.create(env); myAuth.registerValidate({token:'user123',age:100},'local',function(err,isUsefull){ if(isUserfull){ // 注册信息验证成功,可以进行注册 myAuth.register('user123','pwd',{age:100},local,function(err){ if(err){ // 注册失败 return; } // 注册成功 // do something .. }); }else{ // 注册信息验证失败 //err.code || err.msg } }); * ### modifyUserInfo 修改用户信息 modifyUserInfo(token,pwd,userInfo,authMethod,callback) 参数说明: * token 用户的登陆标识 * pwd 登陆密码 * userInfo 用户信息对像 * authMethod 用户类型 * callback 用户信息修改完成后的回调函数,可接受一个`err`参数,当修改信息发生错误时,返回产生的错误信息,如果修改成功,则返回`null` * ### modifyPassword 修改用户登陆密码信息 modifyPassword(token,oldPwd,newPwd,authMethod,callback) 参数说明: * token 用户的登陆标识 * oldPwd 当前密码 * newPwd 新密码 * authMethod 目标的用户类型 * callback 修改完成后的回调函数,可接收一个`err`参数,当修改信息发生错误时,返回产生的错误信息,如果修改成功,则为`null` ## Library * ### create 语法:create(factory) 创建一个Library库,sumeru.Library.create(factory); Library.timeUtils = sumeru.Library.create(function(exports){ exports.formatDate = function(time){ return time.getFullYear(); }; }); * ### getter 使用一个Library Library.timeUtils.formatDate(new Date()); ## Reachability 查看网络连接状态 * ### getStatus 语法:getStatus() 获取当前网络状态 sumeru.reachability.getStatus(); 网络状态有以下三种: * ##### STATUS_OFFLINE 当前处于离线状态 sumeru.reachability.STATUS_OFFLINE; * ##### STATUS_CONNECTING 当前处于网络连接状态 sumeru.reachability.STATUS_CONNECTING; * ##### STATUS_CONNECTED 当前已连接到网络 sumeru.reachability.STATUS_CONNECTED; ## File Uploading * #### Library.fileUploader.init() 完成端上上传文件的初始化 具体方法: var myUploader = Library.fileUploader.init({ routerPath:"/files", onSuccess:function(urlLink){//成功之后的处理,此处有保存文件的逻辑 }, fileSelect:function(e){//用户选择文件之后的处理 }, onProgress:function(e){//进度更新 }, onError:function(e){//出错 }, onAbort:function(e){//中断 }, }); * ##### routerPath 与router中的pattern对应 * ##### onSuccess:function(urlLink) 成功之后的处理,此处有保存文件的逻辑 * ##### fileSelect:function(e) 用户选择文件之后的处理 * ##### onProgress:function(e) 进度更新 * ##### onError:function(e) 当上传出错时在该方法中处理 * ##### onAbort:function(e) 当出现`中断`时在该方法中处理 * #### startUpload() 端上上传文件的方法 myUploader.startUpload(); ## package.js package.js用于将文件之间的依赖关系添加到Clouda中,我们可以使用下面的语法编写该文件: sumeru.packages( 'student.js', 'class/', ..... , 'studentList.js' ) 如果参数为文件夹,则Clouda会加载相应文件夹下的package.js。 并不是在所有文件夹下新建文件或者文件夹后需要修改package.js文件,view文件夹和publish文件夹例外。