Publish
Clouda使用PubSub模型描述数据的传输,其中,publish是发布数据的方法,其运行在Server上,每一个publish文件均需要放置在publish/。
module.exports = function(sumeru){
sumeru.publish(modelName, publishName, function(callback){
}); }
- 1.
- 2.
- 3.
可以看到在sumeru.publish()
中有三个参数,modelName
、publishName
和一个匿名方法function(callback){}
,下面详细介绍这些参数的作用。
-
modelName:
被发布数据所属的Model名称
-
publishName:
所定义的Publish的唯一名称,在一个App内全局唯一,该参数与Controller中subscribe()成对使用。
-
function(callback){}
描述数据发布规则的自定义函数,在这里定义被发布数据所需要符合的条件。自定义函数自身也可接受由subcribe()传入的参数,如:。
-
function(arg1,arg2,...,callback){}
其中arg1, arg2为传入参数,传入参数的数量不限,但需要与对应的subscribe()中所传递的参数数量一致。
-
Subscribe
与sumeru.publish()相对应,我们在Controller中使用env.subscribe()
订阅被发布的数据。其中env是Controller中很重要的一个内置对象,稍后我们还会多次见到。
env.subscribe(publishName, function(collection){ });
- 1.
-
publishName:
所定义的Publish的唯一名称,在一个App内全局唯一,该参数与
sumeru.publish(modelName, publishName,function(callback))
中的publishName
名称需要保持一致。 -
function(collection)
Subscribe成功获得数据时,被调用的响应方法。通常,我们主要在其中完成将订阅得到的数据与视图进行绑定(bind)的工作。
-
collection:
订阅获得的数据Collection对象
-
如果需要向Publish传递参数(在上一节的最后我们曾经提到),则使用如下形式。
env.subscribe(publishName,arg1, arg2, ..., function(collection){});
- 1.
arg1,arg2...等任意数量的参数会被传入sumeru.publish()对应的function(arg1,arg2,...,callback)中。
一个Pub/Sub实例
现有一个学生信息的Model(student),假设Controller希望获取全班同学的信息,我们使用Publish/Subscribe方式实现如下:
-
Publish
module.exports = function(sumeru){ sumeru.publish('student', 'pub-allStudents', function(callback){ var collection = this; collection.find({}, function(err, items){ callback(items); }); }); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
-
Subscribe
env.subscribe("pub-allStudents", function(studentCollection){ });
- 1.
假设我们在这个基础上加一个条件限制,现在只希望获取年龄大于18岁同学的信息。
-
Publish
module.exports = function(sumeru){ sumeru.publish('student', 'pub-adultStudents', function(callback){ var collection = this; collection.find({"age": {$gt:18} }, function(err, items){ callback(items); }); }); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
大家可以看到我们使用了
{"age":{$gt:18}}
的方式表达了“年龄大于age”的约束要求。相似的,“年龄小于18”的表达方式如下:
{"age": {$lt:18} }
- 1.
“大于min且小于max”的表达方式如下:
{"age": {$gt:min}, {$lt:max} }
- 1.
支持的操作符如下:
操作符 含义 $gt 大于 $lt 小于 对应的Subscribe如下
-
Subscribe
env.subscribe("pub-adultStudents",function(studentCollection){ });
- 1.
我们在上面的方式上再加一个条件,现在需要大于18岁男生或者女生的信息,性别由Subscribe来决定,如何实现呢?
-
Publish
module.exports = function(sumeru){ sumeru.publish('student', 'pub-adultStudentsWithGender', function(gender,callback){ var collection = this; collection.find({"age":{$gt:18}, "gender": gender }, function(err, items){ callback(items); }); }); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
在这里可以看出所发布的学生的性别,是由Subscribe决定的。这样来看,一个Publish,可以通过不同的参数,为多个Subscribe服务。从这个角度来讲,Publish有点类似于OO语言中的Class的概念,可以理解为Publish发布的是一类数据。
类似的,对应的Subscribe调用如下:
-
Subscribe
env.subscribe("pub-adultStudentsWithGender","male",function(msgCollection){ });
- 1.
external
Clouda提供了三方数据同步的方法,用来满足从第三方网站/第三方接口获取和同步数据的需求。下面将通过一个例子来说明一次三方数据同步的过程。
1. 定义第三方数据Model
在抓取第三方数据之前,先定义一个三方数据的Model用于描述抓取后数据的结构,在app/model
目录下定义model,三方model定义与普通model定义完全一致
Model.student = function(exports){
exports.config = {
fields : [
{ name : 'name', type : 'text'},
{ name : 'age', type : 'int', defaultValue : 0}
]
} }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
2. 指定三方数据来源与解析方法
在app/publish/
下新增externalConfig.js
文件(文件名任意,推荐使用externalConfig.js),用来指定第三方数据来源与解析方法,需要注意必须为抓取回来的数据指定一个唯一标识uniqueColumn
:
/** * 获取第三方数据信息,由开发者自定义 */ 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;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
3. publish第三方数据
上面制定了第三方数据来源之后,就可以在publish中将其发布出来,注意这里需要使用collection.extfind方法,该方法表示此collection为三方数据,处理数据方式不同。
//与普通的collection.find不同,第三方数据的publish调用collection.extfind方法表示此collection为三方数据
fw.publish('student', 'pubext', function(/** arg1, arg2, arg3...*/ callback){
var collection = this;
collection.extfind('pubext', /** arg1, arg2, arg3...*/ callback); });
- 1.
- 2.
- 3.
- 4.
4. 指定三方增/删/改接口以及数据
如想将本地数据修改同步到三方,并且三方提供相应的post接口,可以在app/publish/
下externalConfig.js
文件中,声明三方增/删/改接口以及数据:
较为紧凑的声明方式
声明中:
-
postUrl
方法用来指定三方post接口的地址信息, 参数type为增量类型,增量类型为'insert','update','delete'三者之一; -
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;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
较为工整的声明方式
较为工整的声明方式根据type将不同操作区分开来。
声明中:
-
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' , headers: { //在此自定义header内容,clouda默认的 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': ... } } }, insertUrl : function(/** arg1, arg2, arg3... */){ return { host : 'some.host.com', path : '/insert', headers: { //在此自定义header内容,clouda默认的 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': ... } } }, updateUrl : function(/** arg1, arg2, arg3... */){ return { host : 'some.host.com', path : '/update', headers: { //在此自定义header内容,clouda默认的 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': ... } } }, 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;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
5. subsribe第三方数据
subscribe方法与普通subscribe无差别,开发者只用关心所订阅的pubName,而不用区分数据来源。
function getExt() {
session.extStudent = env.subscribe('pubext', function(collection, info){
session.bind('extBlock', {
data : collection.find().getData()
});
}); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
sumeru.external.post与sumeru.external.get接口
如果上面的方法不能满足您的需求,Clouda同样提供更底层,更灵活的post和get接口
向第三方发送get请求
var url = "http://some.host.com"; var getCallback = function(data){ console.log(data); } sumeru.external.get(url, getCallback);
- 1.
向第三方发送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);
详细代码和说明请参考《Examples》文档中SpiderNews实例。
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
Controller
如果你曾经接触过MVC模型,那么将会很熟悉Controller的概念。在Clouda中,Controller是每个场景的控制器,负责实现App的核心业务逻辑。每一个Controller文件都放在controller/下。
App.studentList = sumeru.controller.create(function(env, session){ });
- 1.
使用sumeru.controller.create()创建一个名为studentList的Controller。
在Controller中有两个非常重要的对象env和session,env用来绑定Controller的生命周期方法,session用来绑用户数据,下面详细的介绍这两个对象。
env
env用来绑定Controller的生命周期方法,Controller具有以下几个时态:onload()、onrender()、onready()、onsleep()、onresume()、ondestroy()。
-
onload
语法:env.onload(){}
- 1.
onload()是Controller的第一个时态,Controller中需要使用的数据都在这个时态中加载,我们上面谈到过的subscribe()也多在这个时态中使用,方法如下。
App.studentList = sumeru.controller.create(function(env, session){ var getAllStudents = function(){ env.subscribe("pub-allStudents",function(studentCollection){ }); }; env.onload = function(){ return [getAllStudents]; }; });
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
注意:如果您开启了Server端渲染,那么在onload函数中需确保onload中,没有使用前端的js中的变量或函数,比如window,document,Localstorage等
-
onrender
语法:env.onrender(){}
- 1.
当数据获取完成后,这些数据需要显示在视图(View)上,这个过程通过onrender()中的代码来实现,这是Controller的第二个时态,负责完成对视图(View)的渲染和指定转场方式。
env.onrender = function(doRender){ doRender(viewName,transition); };
- 1.
-
viewName
需要渲染的视图(View)名称。
-
transition
定义视图转场,形式如下:
['push', 'left']
- 1.
转场方式:我们提供'none', 'push'、'rotate'、'fade'、'shake'五种转场方式
转场方向:不同的转场方式有不同的转场方向,请参考附录:《API说明文档》
-
onready
语法:env.onready(){}
- 1.
这是Controller的第三个时态,在View渲染完成后,事件绑定、DOM操作等业务逻辑都在该时态中完成;每段逻辑使用session.event包装,从而建立事件与视图block的对应关系。
env.onready = function(){ session.event(blockID,function(){ }); };
- 1.
-
blockID
View中block的id,关于block在接下View中会做详细的介绍。
-
function(){}
事件绑定、DOM操作等业务逻辑在这里完成。例如有一个View如下:
<block tpl-id="studentList"> <button id="submit"> </button> </block>
- 1.
如何对view中的submit做事件绑定呢?可以通过下面代码实现:
env.onready = function(){ session.event("studentList",function(){ document.getElementById('submit').addEventListener('click', submitMessage); }); };
- 1.
- 2.
- 3.
- 4.
在开发移动终端上的应用时常会使用到很多的手势操作,例如
旋转
,放大
,拖动
等等,为了方便开发者快速的集成这些手势,Clouda中内置了事件和手势库Library.touch
,如何使用Library.touch
请查看API手册
中touch
部分。 -
redirect
语法:env.redirect(queryPath,paramMap,isforce)
- 1.
一个Controller跳转到另一个Controller
env.redirect('/studentList',{'class':'101'});
- 1.
-
queryPath
router中pattern的值
-
paramMap
需要向跳转Controller传递的参数
- 1.
-
isforce
是否强制生成一个全新的Controller实例。
-
arguments
语法:env.arguments[pattren,params1,...,paramsN]
- 1.
使用该方法可以获取URL中参数,例如:
URL:http://test.duapp.com/sourcepage/params1/params2/.../paramsN
- 1.
Controller中定义router:
sumeru.router.add( { pattern: '/sourcepage', action: 'App.SourceController' } );
- 1.
- 2.
- 3.
- 4.
那么在该Controller中就可以使用env.arguments[1]到env.arguments[N]获取对应的参数。
session
如果您有数据需要绑定到Controller,可以使用session中的方法:
-
get
语法:session.get(key)
- 1.
获取session中“key”的值
-
set
语法:session.set(key,value)
- 1.
设置session中“key”的值
-
commit
语法:session.commit()
- 1.
当你更新了session的数据时,需要根据新的session的数据更新UI是,您可以使用session.commit()就会触发数据对应视图block的更新。
Controller接收URL中的参数
-
使用env.redirect()方法
当一个Controller(起始Controller)跳转到另一个Controller(目标Controller)时,可以使用
env.redirect()
方法来实现参数的传递,方法如下:-
使用paramMap传递参数
-
在起始Controller中
env.redirect(queryPath ,paramMap);
- 1.
第一个queryPath: 目标Controller在router中“pattern”的值;
paramMap:需要传递的参数
-
目标Controller中使用session.get()方法获取参数
sumeru.controller.create(function(env, session){ session.get(); });
- 1.
-
-
使用URL路径部分传递参数
-
在起始Controller中
env.redirect(queryPath/params1/params2);
- 1.
-
目标Controller中使用session.get()方法获取参数
sumeru.controller.create(function(env, session){ params1 = env.arguments[1]; params2 = env.arguments[2]; });
- 1.
- 2.
- 3.
-
-
实例
-
SourceController.js
sumeru.router.add( { pattern: '/sourcepage', action: 'App.SourceController' } ); App.SourceController = sumeru.controller.create(function(env, session){ env.redirect('/destinationpage/100/200',{'a':100,'b':200}); });
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
-
DestinationController.js
sumeru.router.add( { pattern: '/destinationpage', action: 'App.DestinationController' } ); App.DestinationController = sumeru.controller.create(function(env, session){ console.log(session.get('a')); console.log(session.get('b')); console.log(env.arguments[1]); console.log(env.arguments[2]); });
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
-
跳转后的URL为:http://localhost:8080/debug.html/destinationpage/200/100?a=100&b=200&
开发者也可按照上面的URl格式来拼接一个带参数的URL,关于URL我们会在本文档
URL说明
部分做详细的说明。 -
#p#
Model
我们使用Model来定义App的数据模型,例如在model/下创建一个student.js
Model.student = function(exports){ };
- 1.
在"student"中添加"studentName"、"age"和"gender"三个字段:
Model.student = function(exports){
exports.config = {
fields: [
{name : 'studentName', type: 'string'},
{name : 'age', type: 'int'},
{name : 'gender', type: 'string'}
] }; };
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
-
name
字段的名称
-
type
字段的数据类型,包括"int"、"datetime"、"string"、"object"、"array"、"model"、"collection"。
除以上两种,常用的属性还包括:
-
defaultValue
字段的默认值
{name: 'gender', type: 'string', defaultValue: 'male'}
- 1.
若不提供"gender"值时,则字段的默认值为"male"。
再看一个时间的例子:
{name: 'time', type: 'datetime', defaultValue: 'now()'}
- 1.
若不提供"time"值时,则字段的默认值为当前服务器时间。
-
validation
字段的验证,validation包括以下方法:
-
length[min,max]
字段值得长度在min-max的范围。
-
mobilephone
必须为手机号码格式,长度为11位且必须为数字
-
required
字段值不能为空
-
number
字段值必须为数字
-
unique
字段值必须唯一
更多内置验证方法和自定义验证方法,请参考附录:《API说明文档》
-
-
model
当type值为model和collection时,表示该字段包含一个指向其他model的1:1 或 1:n 的关系。 此时,需同时提供model字段以声明指向的model对象。
{name: 'classes', type: 'model', model: 'Model.classes'}
- 1.
Collection
Collection是Model的集合,我们之前曾使用过的subscribe()返回的结果集即是Collection。
session.studentCollection = env.subscribe("pub-allStudents",function(myCollection){ });
- 1.
session.studentCollection是返回的Collection。可对数据集进行“增、删、查、改”的操作:
-
add
语法:add()
- 1.
使用add()在Collection中添加一行数据。
session.studentCollection.add({ studentName: 'John', age: 18, gender:"male" });
- 1.
- 2.
- 3.
- 4.
- 5.
-
save
语法:save()
- 1.
save()是用于将collection的修改保存到Server,在通常情况下,调用save()方法会自动触发对应视图block的更新。
session.studentCollection.save();
- 1.
-
find
语法:find()
- 1.
使用find()查询Collection中符合条件的所有Model。
session.studentCollection.find();
- 1.
使用条件查询时,例如查找gender为“male”的Model;
session.studentCollection.find({gender:'male'});
- 1.
-
destroy
语法: destroy()
- 1.
使用destroy()从Collection中移除数据,
session.studentCollection.destroy();
- 1.
使用条件删除时,例如删除gender为“male”的Model:
session.studentCollection.destroy({gender:'male'});
- 1.
更多Collection API 请参考附录:《API说明文档》
View
在上一篇文档中我们介绍过Clouda的一个重要特性“随动反馈”,那么“随动反馈”是怎么实现的呢?
Controller的onload()时态里,每一个session.bind的BLOCKID,都对应View中的一个"block"标签。 Clouda使用Block为粒度来标记当数据发生变化时View中需要更新的部分,使用handlebars组件作为模板引擎。
在view中使用“block”标签定义需要更新部分,并定义tpl-id
<block tpl-id="studentList">
<p>
{{#each data}}
{{this.studentName}}
{{/each}}
</p>
</block>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
view中的data来源于Controller中onload()时态的session.bind()
env.subscribe("pub-allStudents",function(studentCollection){ session.bind('studentList', { data : studentCollection.find(), }); });
- 1.
通过以上方法,我们就建立了一个基本的"随动反馈"单位,当订阅的数据发生变化时,View中对应的部分将自动更新。
Handlebars的语法非常易用,但为了更快的开发视图代码,Clouda还额外提供了便捷的工具方法
-
foreach
用于快速遍历一个对象或数组
语法:{{#foreach}}{{/foreach}}
- 1.
用法示例:
<p id="test-foreach-caseB"> {{#foreach customObj}} {{key}} : {{value}} {{/foreach}} </p>
- 1.
- 2.
- 3.
- 4.
- 5.
-
compare
比较两个对象
语法: {{#compare a operator b}} {{else}} {{/compare}}
- 1.
可以使用的operator:
operator == === != !== < <= > >= typeof 用法示例:
{{#compare a "<" b}} a < b {{else}} a >= b {{/compare}} {{#compare a "typeof" "undefined"}} undefined {{/compare}}
- 1.
- 2.
- 3.
- 4.
- 5.
注意:当省略operator时,系统默认使用操作符 ==:
{{#compare 1 1}} 1 == 1 {{/compare}}
- 1.
-
{{$ }}
在View中直接执行Javascript代码,并将返回结果输出在View中。
{{$ alert("data.length"); }}
- 1.
View之间的互相引用
-
{{> viewname}}
在一个View中引用另一个View。
配置view加载路径
一般情况下将编写的View文件都存放在app/view文件夹下,如果编写的view文件不在app/view文件夹下,我们也提供View文件路径配置的方法,框架会在配置路径先寻找需要的View文件:
sumeru.config.view.set('path', 'path/to/');
- 1.
则Clouda会在如下目录中加载视图:
app目录/path/to/view/
- 1.
注意:即使是修改viewpath的情况下,在最内一侧仍然需要有一层view文件夹,如上面路径的最后部分。
Router
Router用于建立URL中pattern与Controller之间的对应关系,添加router的操作通常在Controller文件中定义。
一个Controller可以对应多个URL,一个URL只能对应一个Controller。
-
add
语法: sumeru.router.add({pattern:'' , action:''});
- 1.
使用add()可以在router添加一组pattern与Controller的对于关系,方法如下:
sumeru.router.add( { pattern: '/studentList', action: 'App.studentList' } );
-
pattern
URL中pattern部分的值
-
action
对应Controller的名称
通过add方法在router中添加了URL(其路径部分)和Controller的对应关系,就可以使用 “localhost:8080/debug.html/studentList”运行URL(其路径部分)为"/studentList"对应的 Controller。
同时我们还提供定义默认启动Controller的方法:
-
setDefault
语法: sumeru.router.setDefault(Controller Name)
实例:
sumeru.router.setDefault('App.studentList');
- 1.
在Controller中使用setDefault()后,浏览器中输入“localhost:8080/debug.html”就可以启动该Controller,不需要在URL中带路径部分。
这里使用debug.html为调试模式,关于调试模式在“URL说明”部分会作详细介绍。
为了满足加快view渲染速度的需求,Clouda加入了Server渲染的功能。server渲染默认是开启的,如果想单独禁止某个View在Server渲染,可在Router中通过server渲染开关来禁止server渲染。
sumeru.router.add({
pattern:'/test',
action : 'App.unittest',
server_render:false
})
- 1.
- 2.
- 3.
- 4.
- 5.
router的外部处理器
如果您使用backbone等第三方框架,或是存在已有代码根据URL的变化执行一些逻辑,那么这些需求,都可以通过注册一个router的外部处理器使其保持正常工作。
一个外部处理器的写法:
var processor = function(path){ //do something return true; }
- 1.
添加一个外部处理器:
sumeru.router.externalProcessor.add(processor);
- 1.
添加一个backbone的外部处理器的例子:
sumeru.router.externalProcessor.add(Backbone.Router.extend());
- 1.
server_config
当您有一些配置文件以及敏感信息不想被下发到客户端时,您可以将这些文件放在server_config文件夹下。
例如在应用中使用了一些私密的ip而不想把ip下发到客服端导致安全问题,可将ip的信息配置文件放在server_config文件夹下,方法如下:
在server_config文件夹下新建ip_config.js
sumeru.config({ secret_ip: **.**.**.** });
- 1.
并在server_config/package.js添加文件名:
sumeru.package({ "ip_config.js" });
- 1.
这样ip_config.js文件不会被下发到客户端上,如果需要获取secret_ip的值可在server上使用下面方法:
sumeru.config.get("secret_ip");
- 1.
在server_config文件夹下默认存放的文件为Clouda配置文件,包括:
-
bae.js
-
database.js
-
site_url.js
-
server_library.js
注意:上面四个文件为Clouda保留文件,开发者不可以在server_config文件夹下创建同名的文件,也不可以在上述四个文件中添加内容
Library
有的时候我们会遇到这样的麻烦,比如Model中有一个数据类型为“date”的时间字段,而在View上我想显示的是年,我们可以在View使用{{$ }}方法嵌入JavaScript来实现。
虽然这种方法可以实现,但是不易代码管理,我们需要一个library库的管理机制来解决这个问题,例如你可以将这个时间格式化函数存放在library/下:
-
/library/getTime.js
Library.timeUtils = sumeru.Library.create(function(exports){ exports.formatDate = function(time){ return time.getFullYear(); }; });
- 1.
- 2.
- 3.
- 4.
-
/view/student.html
<block tpl-id="studentList"> <p> {{#each data}} {{$Library.timeUtils.formatDate(this.time)}} {{/each}} </p> </block>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
也可以在controller中调用library库,例如:
-
/controller/student.js
session.bind('studentList', { year : Library.timeUtils.formatDate(time) });
- 1.
通常,在onload,onrender和视图文件中使用到的新增加的Library或Handlebars Helpers,都需要同时配置在server_config/server_library中,方法如下:
打开server_config/server_library.js
sumeru.packages('../library/handlbars_helper.js');
- 1.