设为首页 加入收藏

TOP

80行Lua代码实现一个满足基本要求的模版引擎
2014-11-24 01:45:44 来源: 作者: 【 】 浏览:1
Tags:Lua 代码 实现 一个 满足 基本 要求 模版 引擎

80行Lua代码实现一个满足基本要求的模版引擎,以下内容仅供学习交流,未经严格考虑与测试,切勿用于生产环境。


ltemplate.lua


local insert = table.insert


local remove = table.remove


local concat = table.concat


local format = string.format



local loaded = {}


local partten = "(.-){#([^#].-[^#])#}()"



local content = {}


local cur_content = nil



local function ob_start()


cur_content = {}


insert(content, cur_content)


end



local function ob_get_clean()


local ret = concat(cur_content)


remove(content)


cur_content = content[#content]


return ret


end



local function echo(value)


insert(cur_content, value)


end



local function include(path, params)


local bitcode = loaded[path]



if not bitcode then


local fp = io.open(path, "rb")


local template = fp:read('*a')


fp:close()


local results = {}


local last_endpos = 0


for outside, inside, endpos in template:gmatch(partten) do


insert(results, format("echo(%q)", outside))


insert(results, inside)


last_endpos = endpos


end


insert(results, format("echo(%q)", template:sub(last_endpos)))


results = concat(results, "\n")


bitcode = assert(loadstring(results))


loaded[path] = bitcode


end



local env = {


include = include,


echo = echo,


ob_start = ob_start,


ob_get_clean = ob_get_clean


}


setmetatable(env, {__index = function(tb, k)


return params[k] or _G[k]


end})


setfenv(bitcode, env)


bitcode()


end



for i = 1, 100000 do


ob_start()


include(arg[1], {


params = {


a = '1234',


b = '4321'


}


})


ob_get_clean()


end


master.html









child's personal page - 开源中国社区





<script type="text/java script" src="/js/2012/jquery-1.7.1.min.js">


<script type="text/java script" src="/js/2012/jquery.form.js">


<script type="text/java script" src="/js/2011/fancybox/jquery.fancybox-1.3.4.pack.js">


<script type="text/java script" src="/js/2012/poshytip/jquery.poshytip.min.js">


<script type="text/java script" src="/js/2011/oschina.js ver=20121007">


<script type="text/java script" src="/js/2012/less-1.3.0.min.js">


<script type="text/java script" src="/js/scrolltopcontrol.js">


<script type='text/java script' src='/js/jquery/jquery.atwho.js ver=2013112501'>






{# echo(header) #}




{# echo(content) #}




temp.html,继承master.html


{# ob_start() #}


<script>


alert("hello World")



{# local header = ob_get_clean() #}




{# ob_start() #}



{# for k, v in pairs(params) do #}






{# end #}


{# echo(k) #} {# echo(v) #}


{# local content = ob_get_clean() #}



{# include('master.html', {header = header, content = content}) #}


循环十万次测试渲染速度(阿里云最便宜一款vps)


[root@AY130801221248587d02Z ~]# time lua ltemplate.lua temp.html



real 0m1.867s


user 0m1.862s


sys 0m0.004s


总结


由此可见渲染的速度还是非常快的,可以将此原型用于嵌入式设备中的页面上(用大量js实现的嵌入式设备页面兼容性不好)。而且嵌入式设备的界面需要简单明确,所以也不用太丰富的模版功能。


原理很简单:


1.用lua版的正则把模版内{#与#}之间的内容挖出来,原样输出成lua代码,其它部分则生成使用echo打印到某个缓冲区的lua代码。


2.将这个生成出来的代码使用loadstring编译。


3.通过setfenv实现loadstring后的模拟环境配置(用以提供模版内使用的echo,ob_start等函数,以及传入的参数)


4.执行这个编译后的函数即可。


推荐阅读


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇使用 Objective-C 一年后我对它的.. 下一篇Android手机联系人数据库分析

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: