RingoJS服务端javascript框架入门

鉴客 发布于 2010/10/16 09:43
阅读 2K+
收藏 5
基本概念:
模块(module):一个.js文件就是一个模块,模块名就是 js文件的名字(不含.js)。例如:模块'main'就是脚本main.js,模块'report/graph'就是脚本'report /graph.js'……
.js文件要满足条件才能作为模块来使用,即脚本内的要导出的函数都必须是exports对象的属性,参 考一下actions.js即可明白。
默认文档:这个框架的默认文档路径是index,即访问 'http://localhost:8080/'等同于访问
'http://localhost:8080/index',访问 '/admin/users/'等同于访问'/admin/users/index'。
skin: 这个框架使用自己开发的技术来渲染页面。做法是,载入一个文本文件,将其中<%%>之中的部分用变量或者一些函数替换掉。这个文本文件就叫做 skin,而<%%>之间的部分叫做宏(macro)。框架通过插件的形式插入了一些macro,比如render、subskin、for 等等。
----------------------------------
基 本脚本文件清单:
main.js
config.js
actions.js
skins/base.html
----------------------------------
说 明:
main.js - 程序启动工具,调用$RINGO_HOME/bin/ringo $WEBAPP_PATH/main.js即可启动应用。不要修改这个文件。
config.js - 整个web应用的配置节点,它通过指定一些信息让框架去查找相应的配置。参见此文件的注释。不要修改这个文件中除了exports.urls以外的内容。
actions.js - 这个文件中有url到脚本的映射。注意:这个框架不是映射到脚本,而是映射到函数。
skins/base.html - 这是整个框架的基本页面,不过用哪个基本页面是在实际页面里指定的。
---------------------------------
config.js 说明:
最好只修改exports.urls。这是从url到函数的映射。
例如(来自demo):
*************
var {resolve} = require('fs');
exports.httpConfig = {
staticDir: './static'
};
exports.urls = [
[ '/mount/point', './webmodule' ],
[ '/storage', resolve(module.path, '../storage/config') ],
[ '/', './actions' ]
];
*************
注:这里的 resolve函数是从fs模块里引入的。
urls是一个数组,每个元素代表一个映射。请求到来时,从最上面的元素开始向下进行匹 配,遇到匹配的即调用相应的函数,并终止这个匹配过程,不再向下匹配。
每一个元素还是一个数组,第一个元素是url(似乎可以用正 则表达式),第二个是元素是映射到的模块,第三个是映射到的函数名称,第四个是函数的参数。第三和第四个元素可选。
比如上面的第三 个映射:[ '/', './actions' ]
其中'/'表示浏览器请求任何以'/'开头的url时都匹配这个映射(当然,根 据前面的元素,'/mount/point/'开头的和'/storage/'开头的都被前面的匹配了,不会匹配到这个元素)。当匹配了这个映射的时候, 框架会从指定的模块'actions'里面找相应的函数进行调用。这里没有配置函数名,那么当请求/index时会调用模块'actions'里的 exports.index函数(同名函数),请求/settings时会调用exports.settings函数。
目前还不知 道多层的路径如/settings/roles如何映射。
映射的第四个元素,即函数的参数可以暂时不考虑,可能不会经常使用。其用 途是,你可以将多个url映射到同一个函数,然后根据传入的参数来区别。例如:
['/notification', 'notices', 'listNotices', 'notices']和['/publishments',
'notices', 'listNotices', 'pubs'],那么两个请求映射到同一个函数(notices.js里的exports.listNotices函数)。如果函数原型如下:
function(req, noticeType),那么请求/notifications调用的时候,传入noticeType为'notices';
而 /publishments调用的时候,传入noticeType为'pubs'。
注:参数应该可以传多个,并且不限于字符串类 型。
----------------------------------
actions.js 说明:
根据默认的config.js,各个请求都映射到这个模块,url路径同名的函数上。
初始的 actions.js如下:
**********************
include('ringo/webapp/response');
exports.index = function (req) {
return skinResponse('skins/index.html', {
content: "It's working!"
});
};
**********************
其 中,skinResponse函数来自上面引入的模块'ringo/webapp/response',用来将skin渲染并转换为应答。后面的json 表示要渲染的变量,这里只有一个content,页面'skins/index.html'里的<% content %>的内容会被替换为这里指定的值(It's working!)。
----------------------------------
skins/base.html 说明:
看这段代码:
************************
<title><% title %></title>
************************
这 里的<% title %>的含义,是把渲染参数'title'的值输出到这里。渲染参数来自skinResponse函数的第二个参数的属性,如果没有title属性, 这里什么都不输出。
看这段代码:
************************
<% subskin content %>
Overwrite this subskin to add content.
************************
这 里的<% subskin content %>表示定义了一个名为content的subskin。这个subskin从这个macro后面开始,直到下一个<% subskin XXXXXX %>为止(否则直到文件结束都属于这个subskin)。subskin的内容不直接显示在页面上,就是说,你在skin文件的最后部分定义了 subskin,但是其内容'Overwrite this subskin to add content.'并不会直接显示在页面的这个部位,需要你利用render宏来输出到指定的位置。
看 这段代码:
***********************
<body>
<% render content %>
</body>
***********************
这 里的<% render content %>表示把名为content的subskin输出到这里。如果没有这个subskin,那么这里什么也不输出。
--------------------------------
skins/index.html 说明:
根据前面config.js和actions.js的配置,你的应用的/index会用这个skins /index.html来进行渲染。
这个skin初始的代码:
**********************
<% extends ./base.html %>
<% subskin content %>
<% content %>
**********************
这 里,<% extends ./base.html %>显然是本页扩展base.html的意思。
<% subskin content %>表示建立一个名为content的subskin。因为base.html也声明了一个同名的subskin,所以显然这里的把前一个给覆盖掉 了。根据猜测,可以认为按照subskin定义的顺序,由后面的覆盖前面的。
-------------------------------
详 细的skin说明,参考http://ringojs.org/demo/skins,或者自己运行demo后看skins部分。
下 面是一个循环的例子:
把初始的actions.js里面的exports.index函数改为:
************************
exports.index = function (req) {
return skinResponse('skins/index.html', {
tablerow: [{
id: 1,
name: 'Ryu',
nation: 'Japan'
}, {
id: 2,
name: 'Ken',
nation: 'US'
}, {
id: 3,
name: 'Chunli',
nation: 'China'
}, {
id: 4,
name: 'Cammy',
nation: 'UK'
}]
});
};
***********************
这 样,要渲染的json对象没有了content属性,而增加了一个数组属性tablerow。
再把初始的index.html里的 名为content的subskin改成:
***********************
<% subskin content %>
<table>
<tr><td>ID</td><td>Name</td><td>Nation</td></tr>
<% for row in <% tablerow %> render trow %>
</table>
**********************
这 里没有了content的输出,而改为输出tablerow。但是因为要循环,所以还要定义另一个subskin:
**********************
<% subskin trow %>
<tr><td><% row.id %></td><td><% row.name %></td><td><% row.nation %></td></tr>
**********************
这 段代码加在index.html的最后面即可。
for是一个表示循环的宏,它每循环一次,从tablerow里面提取一个元素并临 时命名为row,然后在这里(即你写这个for宏的地方)利用render宏输出一次名为trow的subskin。
在名为 trow的subskin里,即可输出row的各个属性。
加载中
返回顶部
顶部