渲染html到页面中,在koa中可以这么干:
- app.get('/',function*(){
 - this.body = "<p>'+title+'</p>";
 - })
 
但问题很大,模板混入到js逻辑了,非常不利于维护,基于 mvc 模式,我们需要将html模板抽离到 view 中方便维护,这时候我们就需要一款模板渲染引擎。
为什么选择xtemplate
适用于 koa 的模板引擎选择非常多,比如 jade、ejs、nunjucks、xtemplate 等。
为什么选择 xtemplate 呢?
上手难度
jade 无疑是最独特,上手难度最高,特别是将 html 转成 jade 风格的代码,需要一些成本和适应,特别是空格敏感,经常引起模块渲染报错:
- body
 - h1 Jade - node template engine
 - #container.col
 - if youAreUsingJade
 - p You are amazing
 - else
 - p Get on it!
 
但 jade 在 express 中拥有广泛的群众基础,所以从 express 转到 koa,jade 是个不错的选择,但我一直认为 jade 不是最佳的模板选择。
ejs、nunjucks、xtemplate 的上手难度差不多,但ejs的扩展写法有些诡异,特别是 filter 的写法:
- <p><%=: users | first | capitalize %></p>
 
xtemplate 相对于 nunjucks 的优势是,模板的逻辑写法体验更接近js(ejs的逻辑表达也很接近js),上手更为简单,来看下同样一个 if 判断的写法差异。
xtemplate:
- {{#if(variable===0)}}
 - It is true
 - {{/if}}
 
nunjucks:
- {% if variable == 0 %}
 - It is true
 - {% endif %}
 
所以上手难度:xtemplate < nunjucks < ejs < jade 。
功能的强大度
四款模板引擎必备几样功能都具备:变量、逻辑表达式、循环、layout、include、宏、扩展等。
nunjucks 无疑是功能最全面的模板引擎,xtemplate 拥有 nunjucks 大部分的特性,除了filter,但 xtemplate 拥有非常强悍的拓展性:
- xtpl.addCommand('money',function(scope, option){
 - var money = option.params[0];
 - if(typeof money !== 'number') return '';
 - //金额除以100(接口返回的金额都是以分为单位,转成元)
 - var s = Number(money)/100;
 - return s;
 - })
 
模板中使用:
- {{money(10000)}}
 
nunjucks 与 xtemplate 都拥有实用的宏定义功能:
- {{#macro("test","param", default=1)}}
 - param is {{param}} {{default}}
 - {{/macro}}
 
模板中使用:
- {{macro("test","2")}}
 
输出内容:
- param is 2 1
 
jade 中的 Mixins,ejs 中的 function 也可以实现类似的抽取公用html代码块的目的 。
如果真要分个高下:nunjucks > xtemplate > jade > ejs 。
是否支持前后端混用
jade 直接淘汰,相信在前端js领域一般不会选择 jade 来渲染。
nunjucks 也使用的比较少(ejs其实也少),更多人会选择使用 handlebars 。
xtemplate 目前在阿里的系统中前后端混用中已经得到论证,节约了模板前后端转换的时间。
事实上是否支持前后端混用不是决定性因素,特别是在 angularjs 盛行的年代。
性能考量
它们都很快,其实性能都不是问题,真要较真的话,xtemplate 会更优秀些,可以看 xtemplate benchmark。
个人觉得性能不是决定性因素。
基于上述几点考虑,推荐使用 xtemplate 。
		
 PHP处理HTTP请求的几种方式
		
		
 2016/09/05 17:48 | by 刘新修 ]
		GET,一般是明文的,比如XXX.php?a=1&b=2,这里的a,b就必须用GET方式接收,接收代码如下:
$a = $_GET['a'];
$b = $_GET['b'];
//接收a,b两个变量
POST,一般是隐藏的非明文的,一般表单设置成POST的,接收方式如下:
//比如有个表单,表单中有两个文本框,name 分别是 a,b,那么代码如下:
$a = $_POST['a'];
$b = $_POST['b'];
另外:$_REQUEST,可以同时接收GET、POST的变量,用法如:
$_REQUEST['a'];//接收变量a,a可以是GET的也可以是POST的
另外说说PHP获取POST请求的几种方式:
方法1、最常见的方法是:$_POST['fieldname'];
说明:只能接收Content-Type: application/x-www-form-urlencoded提交的数据
解释:也就是表单POST过来的数据
方法2、file_get_contents(“php://input”);
说明:
允许读取 POST 的原始数据。
和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。
php://input 不能用于 enctype=”multipart/form-data”。
解释:
对于未指定 Content-Type 的POST数据,则可以使用file_get_contents(“php://input”);来获取原始数据。
事实上,用PHP接收POST的任何数据都可以使用本方法。而不用考虑Content-Type,包括二进制文件流也可以。
所以用方法二是最保险的方法。
方法3、$GLOBALS['HTTP_RAW_POST_DATA'];
说明:
总是产生 $HTTP_RAW_POST_DATA 变量包含有原始的 POST 数据。
此变量仅在碰到未识别 MIME 类型的数据时产生。
$HTTP_RAW_POST_DATA 对于 enctype=”multipart/form-data” 表单数据不可用
如果post过来的数据不是PHP能够识别的,可以用 $GLOBALS['HTTP_RAW_POST_DATA']来接收,
比如 text/xml 或者 soap 等等
解释:
$GLOBALS['HTTP_RAW_POST_DATA']存放的是POST过来的原始数据。
$_POST或$_REQUEST存放的是 PHP以key=>value的形式格式化以后的数据。
但$GLOBALS['HTTP_RAW_POST_DATA']中是否保存POST过来的数据取决于centent-Type的设置,即POST数据时 必须显式示指明Content-Type: application/x-www-form-urlencoded,POST的数据才会存放到 $GLOBALS['HTTP_RAW_POST_DATA']中。
		
 node.js 获取http url路径中的各个参数
		
		
 2016/09/05 08:52 | by 刘新修 ]
		假设URL为:http://localhost:8888/select?name=a&id=5
- http.createServer(function(request,response){
 - var pathname = url.parse(request.url).pathname; //pathname => select
 - var arg = url.parse(request.url).query; //arg => name=a&id=5
 - console.log("Request for " + arg );
 - var str = querystring.parse(arg); //str=> {name:'a',id:'5'}
 - var arg1 = url.parse(request.url, true).query; //arg1 => {name:'a',id:'5'}
 - console.log("Request for " + arg1 );
 - var name = querystring.parse(arg).name; //name => a
 - console.log("name = "+name);
 - console.log("Request for " + pathname + " received.");
 - }).listen(8888);
 
//querystring.parse(arg) => { name: 'a', id: '5' }
var url = require('url');
var a = url.parse('http://example.com:8080/one?a=index&t=article&m=default');
console.log(a);
 
//输出结果:
{ 
    protocol : 'http' ,
    auth : null ,
    host : 'example.com:8080' ,
    port : '8080' ,
    hostname : 'example.com' ,
    hash : null ,
    search : '?a=index&t=article&m=default',
    query : 'a=index&t=article&m=default',
    pathname : '/one',
    path : '/one?a=index&t=article&m=default',
    href : 'http://example.com:8080/one?a=index&t=article&m=default'
}
		
 node.js post json格式数据到服务器的几种方法
		
		
 2016/09/04 20:31 | by 刘新修 ]
		json格式被越来越多的开发者说青睐,我们常常在接口定义时使用这种格式参数进行数据交换.
今天主要给大家从繁到简的几个node.js下使用的提交 json个数参数的方式方法.
下面示例中出现的参数都做了处理,拷贝代码后需要更改这些参数同时自己写一个接收json格式的api,请求成功后再返回json格式
(一) node.js 原生自带http模块,可以解决基于http协议下的请求及回发,执行效率高,但是好多东西需要开发人员自己动手来实现,看下面代码
- var http=require('http');
 - var body = {
 - "data":{
 - "channel" : "aaa",
 - "appkey" : "bbb"
 - },
 - "sign" : "22334455",
 - "token" : "bb667788"
 - };
 - var bodyString = JSON.stringify(body);
 - var headers = {
 - 'Content-Type': 'application/json',
 - 'Content-Length': bodyString.length
 - };
 - var options = {
 - host: '127.0.0.1',
 - port: 3005,
 - path: '/Config',
 - method: 'POST',
 - headers: headers
 - };
 - var req=http.request(options,function(res){
 - res.setEncoding('utf-8');
 - var responseString = '';
 - res.on('data', function(data) {
 - responseString += data;
 - });
 - res.on('end', function() {
 - //这里接收的参数是字符串形式,需要格式化成json格式使用
 - var resultObject = JSON.parse(responseString);
 - console.log('-----resBody-----',resultObject);
 - });
 - req.on('error', function(e) {
 - // TODO: handle error.
 - console.log('-----error-------',e);
 - });
 - });
 - req.write(bodyString);
 - req.end();
 
http模块比较原始,请求参数里我们要手动指定请求头类型,头长度,请求方式,主机头和端口等.
当我们将json格式参数post上去以后,得到的response 对象需要我们在 data 事件上手动处理获取到的数据, end 事件表示接收数据流已结束, error 事件是当回发数据发生错误时将自动触发此事件响应函数
(二)
大名鼎鼎的 request 模块上场了,这个模块帮我们做了很多我们不关心的东西,比如请求后得到的 response 对象,我们将不会非常繁琐的去手动捕获 data ,end ,error 事件. 取而代之的是回调函数里直接将我们关心的回发数据放到了一个变量里,看下面的代码:
此模块并发node.js 原生自带模块,首先需要 npm install request ,下面代码的参数同样做了处理
- var request=require('request');
 - var options = {
 - headers: {"Connection": "close"},
 - url: 'http://127.0.0.1:3005/Config',
 - method: 'POST',
 - json:true,
 - body: {data:{channel : "aaa",appkey : "bbb"},sign : "ccc",token : "ddd"}
 - };
 - function callback(error, response, data) {
 - if (!error && response.statusCode == 200) {
 - console.log('----info------',data);
 - }
 - }
 - request(options, callback);
 
代码明显比第一种方式少了很多,callback 里面的 data 参数就是我们请求路径后得到的内容,而且我们在 options 中指定了 json:true ,所以请求和回发的数据自动转变成了 json 对象.我们看下这次的运行结果:
node request.js
下面还有一种更简单的方法和大家分享
(三)
也是一个第三方模块,叫做 request-json
看名字就非常容易理解,有关json 格式参数的请求模块,使用也非常方便.
首先 npm install request-json 安装此模块,定义好 json请求参数对象,见下面代码:
- request = require('request-json');
 - var client = request.newClient('http://127.0.0.1:3005/');
 - var data = {data:{channel : "aaa",appkey : "bbb"},sign : "4444",token : "555"};
 - client.post('Config', data, function(err, res, body) {
 - console.log(res.statusCode,body);
 - });
 
返回的body 也是自动序列化成json对象,见运行结果
前面的 200 是 res.statusCode 回发状态值,接着输出的是我们得到的json对象,无论从使用还是理解上,都是最简单的一种方法.
		
 nodeJs构建一个HttpServer
		
		
 2016/09/04 20:19 | by 刘新修 ]
		将下面代码放入server.js中
- var http = require("http");
 - http.createServer(function(request, response) {
 - console.log('request received');
 - response.writeHead(200, {"Content-Type": "text/plain"});
 - response.write("Hello World");
 - response.end();
 - }).listen(8888);
 - console.log('server started');
 
执行node server.js 
打开http://localhost:8888/,页面显示Hello World 
- var http=require('http');
 - var data={key:'value', hello:'world'};
 - var srv=http.createServer(function (req, res) {
 - res.writeHead(200,{'Content-Type': 'application/json'});
 - res.end(JSON.stringify(data));
 - });
 - srv.listen(8080,function() {
 - console.log('listening on localhost:8080');
 - });
 
		
 nodejs 提供了一个 node-uuid 模块用于生成 uuid:
		
		
 2016/09/04 14:07 | by 刘新修 ]
		首先执行:npm install node-uuid -g
- var uuid = require('node-uuid');
 - //var uuid = require('/usr/local/nodejs/lib/node_modules/node-uuid');
 - console.log(uuid.v1())
 - console.log(uuid.v4())
 
注明:如果在linux下编译安装node可以使用软连接ls 或这直接写绝对路径引入需要的nmp模块!
v1 是基于时间戳生成uuid
v4是随机生成uuid
结果:
- 57af5b10-3a76-11e5-922a-75f42afeee38
 - f3917fb9-9bde-4ec1-a7cf-966251b3d22a
 
		
 nodejs中exports与module.exports的区别
		
		
 2016/09/04 13:17 | by 刘新修 ]
		你肯定非常熟悉nodejs模块中的exports对象,你可以用它创建你的模块。例如:(假设这是rocker.js文件)
- exports.name = function() {
 - console.log('My name is Lemmy Kilmister');
 - };
 
在另一个文件中你这样引用
- var rocker = require('./rocker.js');
 - rocker.name(); // 'My name is Lemmy Kilmister'
 
那到底Module.exports是什么呢?它是否合法呢?
其实,Module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是Module.exports而不是exports。
所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是Module.exports本身不具备任何属性和方法。如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。
修改rocker.js如下:
- module.exports = 'ROCK IT!';
 - exports.name = function() {
 - console.log('My name is Lemmy Kilmister');
 - };
 
再次引用执行rocker.js
- var rocker = require('./rocker.js');
 - rocker.name(); // TypeError: Object ROCK IT! has no method 'name'
 
发现报错:对象“ROCK IT!”没有name方法
rocker模块忽略了exports收集的name方法,返回了一个字符串“ROCK IT!”。由此可知,你的模块并不一定非得返回“实例化对象”。你的模块可以是任何合法的javascript对象--boolean, number, date, JSON, string, function, array等等。
你的模块可以是任何你设置给它的东西。如果你没有显式的给Module.exports设置任何属性和方法,那么你的模块就是exports设置给Module.exports的属性。
下面例子中,你的模块是一个类:
- module.exports = function(name, age) {
 - this.name = name;
 - this.age = age;
 - this.about = function() {
 - console.log(this.name +' is '+ this.age +' years old');
 - };
 - };
 
可以这样应用它:
- var Rocker = require('./rocker.js');
 - var r = new Rocker('Ozzy', 62);
 - r.about(); // Ozzy is 62 years old
 
下面例子中,你的模块是一个数组:
- module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];
 
可以这样应用它:
- var rocker = require('./rocker.js');
 - console.log('Rockin in heaven: ' + rocker[2]); //Rockin in heaven: Ronnie James Dio
 
现在你明白了,如果你想你的模块是一个特定的类型就用Module.exports。如果你想的模块是一个典型的“实例化对象”就用exports。
给Module.exports添加属性类似于给exports添加属性。例如:
- module.exports.name = function() {
 - console.log('My name is Lemmy Kilmister');
 - };
 
同样,exports是这样的
- exports.name = function() {
 - console.log('My name is Lemmy Kilmister');
 - };
 
请注意,这两种结果并不想同。前面已经提到module.exports是真正的接口,exports只不过是它的辅助工具。推荐使用exports导出,除非你打算从原来的“实例化对象”改变成一个类型。
		
 gcc-4.4.7升级至gcc-5.3.0 后编译安装node-v4.5.0
		
		
 2016/09/02 15:19 | by 刘新修 ]
		yum -y install gcc gcc-c++
		
 ArtTemplate_List 实例
		
		
 2016/08/02 16:56 | by 刘新修 ]
		ArtTemplate_List 实例1
- <!DOCTYPE HTML>
 - <html>
 - <head>
 - <meta charset="UTF-8">
 - <title>basic-demo</title>
 - <script src="../dist/template.js"></script>
 - </head>
 - <body>
 - <div id="content"></div>
 - <script id="test" type="text/html">
 - {{if isAdmin}}
 - <h1>{{title}}</h1>
 - <ul>
 - {{each list as value i}}
 - <li>索引 {{i + 1}} :{{value}}</li>
 - {{/each}}
 - </ul>
 - {{/if}}
 - </script>
 - <script>
 - var data = {
 - title: '基本例子',
 - isAdmin: true,
 - list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
 - };
 - var html = template('test', data);
 - document.getElementById('content').innerHTML = html;
 - </script>
 - </body>
 - </html
 
ArtTemplate_List 实例2
- <!DOCTYPE HTML>
 - <html>
 - <head>
 - <meta charset="UTF-8">
 - <title>compile-demo</title>
 - <script src="../dist/template.js"></script>
 - </head>
 - <body>
 - <h1>在javascript中存放模板</h1>
 - <div id="content"></div>
 - <script>
 - var source = '<ul>'
 - + '{{each list as value i}}'
 - + '<li>索引 {{i + 1}} :{{value}}</li>'
 - + '{{/each}}'
 - + '</ul>';
 - var render = template.compile(source);
 - var html = render({
 - list: ['摄影', '电影', '民谣', '旅行', '吉他']
 - });
 - document.getElementById('content').innerHTML = html;
 - </script>
 - </body>
 - </html>
 
- <!DOCTYPE HTML>
 - <html>
 - <head>
 - <meta charset="UTF-8">
 - <title>basic-demo</title>
 - <script src="../dist/template.js"></script>
 - </head>
 - <body>
 - <h1>在javascript中存放模板</h1>
 - <div id="content"></div>
 - <script>
 - /***** 小模版 *****/
 - var source=''
 - +'<ul>'
 - + '{{each list as value i}}'
 - + '<li>索引 {{i+1}} :{{value}}</li>'
 - + '{{/each}}'
 - +'</ul>';
 - /***** 定义变关联逻辑代码片段(小模版) *****/
 - var connectJs=template.compile(source);
 - /***** 最终的数据源等于==逻辑代码关联数据 *****/
 - var htmlData=connectJs({
 - list: ['摄影', '电影', '民谣', '旅行', '吉他']
 - });
 - /***** 把最终处理后的数据源插入到页面 *****/
 - document.getElementById('content').innerHTML=htmlData;
 - </script>
 - </body>
 - </html>
 
实例访问地址:http://code.liuxinxiu.com/jstpl/artTemplate/demo/best.html
include嵌入子模板:
- <!DOCTYPE HTML>
 - <html>
 - <head>
 - <meta charset="UTF-8">
 - <title>include-demo</title>
 - <script src="../dist/template.js"></script>
 - </head>
 - <body>
 - <div id="content"></div>
 - <script id="test" type="text/html">
 - <h1>{{title}}</h1>
 - {{include 'list'}}
 - </script>
 - <script id="list" type="text/html">
 - <ul>
 - {{each list as value i}}
 - <li>索引 {{i + 1}} :{{value}}</li>
 - {{/each}}
 - </ul>
 - </script>
 - <script>
 - var data = {
 - title: '嵌入子模板',
 - list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
 - };
 - var html = template('test', data);
 - document.getElementById('content').innerHTML = html;
 - </script>
 - </body>
 - </html>
 
理解部分(使用普通for循环加声明语法,进行数组遍历)1:
- <!DOCTYPE html>
 - <html lang="en">
 - <head>
 - <meta charset="UTF-8">
 - <title>AtrTemplate</title>
 - </head>
 - <body>
 - <div id="content"></div>
 - <script src="js/template-native.js"></script>
 - <script id="test" type="text/html">
 - <%for( i = 0; i < content.length; i++) {%>
 - <h1><%=content[i].title%></h1>
 - <p>条目内容 : <%=content[i].list%></p>
 - <%}%>
 - // 等同于普通的for循环,在普通的for循环上给每一行语法声明加上<% xx %>
 - // 等同于普通的for循环,在普通的for循环上取值部分加上类似jsp的变量声明 <%= xx %>
 - //for(i=0;i<content.length;i++){
 - // <h1><%=content[i].title%></h1>
 - // <p>条目内容 : <%=content[i].list%></p>
 - //}
 - </script>
 - <script>
 - /***** 自造数据,content为数组List便于测试循环 *****/
 - var data={
 - content:[
 - {
 - title: "artTemplate",
 - list: "新一代 javascript 模板引擎",
 - },
 - {
 - title: "特性",
 - list: "性能卓越,执行速度快"
 - }
 - ]
 - };
 - /***** 用template映射数据到逻辑代码区域|也可以理解称给逻辑代码片段绑定数据源 *****/
 - var html=template('test',data);
 - /***** 选择页面Dom元素,插入处理后的数据 *****/
 - document.getElementById("content").innerHTML=html;
 - </script>
 - </body>
 - </html>
 
理解部分(使用普通for循环加声明语法,进行双层嵌套数组遍历)2:
- <!DOCTYPE html>
 - <html lang="en">
 - <head>
 - <meta charset="UTF-8">
 - <title>AtrTemplate -- 简介</title>
 - </head>
 - <body>
 - <div id="content"></div>
 - <script src="js/template-native.js"></script>
 - <script id="listtemp">
 - </script>
 - <script id="test" type="text/html">
 - //循环嵌套,循环数组里的数组
 - <%for(i=0;i<content.length;i++){%>
 - <h1><%=content[i].title%></h1>
 - <ul>
 - <%for(j=0;j<content[i].list.length;j++){%>
 - <li><%=content[i].list[j]%></li>
 - <%}%>
 - </ul>
 - <%}%>
 - </script>
 - <script>
 - var data={
 - content:[
 - {
 - title: "artTemplate",
 - list:["新一代 javascript 模板引擎"]
 - },
 - {
 - title: "特性",
 - list: [
 - "性能卓越,执行速度通常是 Mustache 与 tmpl 的 20 多倍",
 - "支持运行时调试,可精确定位异常模板所在语句",
 - " 对 NodeJS Express 友好支持",
 - "安全,默认对输出进行转义、在沙箱中运行编译后的代码(Node版本可以安全执行用户上传的模板)",
 - " 支持include语句",
 - "可在浏览器端实现按路径加载模板",
 - "支持预编译,可将模板转换成为非常精简的 js 文件",
 - "模板语句简洁,无需前缀引用数据,有简洁版本与原生语法版本可选",
 - "支持所有流行的浏览器"
 - ]
 - }
 - ]
 - };
 - /***** 用template映射数据到逻辑代码区域|也可以理解称给逻辑代码片段绑定数据源 *****/
 - var html=template('test',data);
 - /***** 选择页面Dom元素,插入处理后的数据 *****/
 - document.getElementById("content").innerHTML=html;
 - </script>
 - </body>
 - </html>
 
- /***** 格式化日期 *****/
 - function formatDate(_strTime,_format){
 - var date=new Date(_strTime);
 - var paddNum=function(num){
 - num+="";
 - return num.replace(/^(\d)$/,"0$1");
 - }
 - //指定格式字符
 - var cfg={
 - yyyy:date.getFullYear() //年:4位
 - ,yy :date.getFullYear().toString().substring(2) //年:2位
 - ,M :date.getMonth() + 1 //月:如果1位的时候不补0
 - ,MM :paddNum(date.getMonth()+1) //月:如果1位的时候补0
 - ,d :date.getDate() //日:如果1位的时候不补0
 - ,dd :paddNum(date.getDate()) //日:如果1位的时候补0
 - ,hh :date.getHours() //时
 - ,mm :date.getMinutes() //分
 - ,ss :date.getSeconds() //秒
 - }
 - _format||(_format="yyyy-MM-dd hh:mm:ss");
 - return _format.replace(/([a-z])(\1)*/ig,function(m){return cfg[m];});
 - }
 - formatDate("Tue Jul 16 01:07:00 CST 2013","yyyy-MM-dd ");
 




  
 
 
 
 
 


