-
Notifications
You must be signed in to change notification settings - Fork 64
2.1.Smarty模板
Her 采用 Smarty 作为模板系统,并在 Smarty 上扩展了一些用于性能优化、模块化开发的插件。
{html}
{/html}
标签是 Her 用来控制模板输出的插件,使用时替换原生 <html>
</html>
标签。
参考输出方式(TODO)
{head}
{/head}
标签是 Her 用来控制模板输出的插件,使用时替换原生 <head>
</head>
标签。
参考输出方式(TODO)
{title}
{/title}
标签是 Her 用来收集页面标题的插件,使用时替换原生 <title>
</title>
标签。
参考输出方式(TODO)
{body}
{/body}
标签是 Her 用来控制模板输出的插件,使用时替换原生 <body>
</body>
标签。
参考输出方式(TODO)
{html her="common:static/lib.js"}
{head}
{title}This is title{/title}
{require name="common:reset.css"}
...some thing else in head.
{/head}
{body}
...some thing outside before pagelet.
{require name="common:page.css"}
{pagelet id="mypagelet"}
{require name="module:pagelet.css"}
...some thing inside pagelet.
{/pagelet}
...some thing outside after pagelet.
{/body}
{/html}
运行时输出:
<!DOCTYPE html>
<html>
<head>
<title>This is title</title>
<!-- 所有pagelet之外依赖的css资源和*{html}*标签指定的框架js,会直接同步输出,其他资源都是由前端loader异步加载 -->
<link rel="stylesheet" type="text/css" href="*reset.css的真实发布路径*" />
<link rel="stylesheet" type="text/css" href="*page.css的真实发布路径*" />
...some thing else in head.
</head>
<body>
...some thing outside before pagelet.
<div id="mypagelet"></div><!-- pagelet先只输出占位div,其内容和资源在后面输出 -->
...some thing outside after pagelet.
<!-- 所有pagelet之外依赖的css资源和*{html}*标签指定的框架js,会直接同步输出,其他资源都是由前端loader异步加载 -->
<script src="*lib.js的真实发布路径*"></script>
<!-- 所有同步输出的资源,用*BigPipe.loadedResource*注册一下,告诉前端loader它们已经加载了 -->
<script>BigPipe.loadedResource(["c8ade30","3365e3d","46b833c"]);</script>
<!-- 下面会依次输出每一个pagelet的内容和资源,包括*{html}*,*{html}*是一个特殊的最顶层的pagelet -->
<!-- *{html}*资源输出begin,html包含的dom其实是同步输出到页面的,即上面的 "some thing outside pagelet." -->
<script>
BigPipe.hooks["__cb_0_1"]=function(){/*some code...*/};
BigPipe.setResourceMap({
"c8ade30":{
"src":"*lib.js的真实发布路径*",
"type":"js",
"deps":[],
"mods":["common:static/lib.js"]
},
"3365e3d":{
"src":"*reset.css的真实发布路径*",
"type":"css",
"deps":[],
"mods":["common:reset.css"]
},
"46b833c":{...}
});
BigPipe.onPageletArrive({"id":null,"children":["mypagelet"],"deps":{"beforedisplay":["3365e3d","46b833c"],"load":[]},"hooks":{"load":["__cb_0_1"]}});
</script>
<!-- *{html}*输出end -->
<!-- *{pagelet}*内容和资源输出begin -->
<code id="__cnt_mypagelet" style="display:none"><!--
...some thing inside pagelet.
--></code>
<script>
BigPipe.setResourceMap({});
BigPipe.onPageletArrive({"id":"mypagelet","css":["依赖的 CSS 资源*pagelet.css的id*"],"js":["依赖的 JS 资源"],"container_id":"__cnt_mypagelet"});
</script>
<!-- *{pagelet}*内容和资源输出end -->
</body>
</html>
{pagelet}
{/pagelet}
标签用来标记页面中的独立区块,该区块可以被单独的加载和渲染,并且可以通过编程控制渲染时机。
生成的标签由 tag
参数指定,默认为 "div"
。
渲染方式 her-renderMode
default
(默认值),默认输出方式,html 输出到注释,通过 js 添加到 dom
server
,直接输出 html 内容到页面,同时将 beforedisplay 依赖加入 root context,其他同 default
lazy
,只输出 pagelet 占位标签,不输出其他数据,需要手动通过 Bigpipe.fetch() 异步加载,通过 BigPipe.lazyPagelets 可以获取lazy pagelets
none
,不输出,直接跳过 pagelet,可通过条件判断控制是否输出 pagelet
注意:
server|lazy
只适用于同步渲染,quickling 时会忽略,按 default
方式输出;
server
需要其父 pagelet 渲染模式也是 server
;
lazy|none
会继承给子 pagelet (忽略子 pagelet 的renderMode
属性);
实际输出时的 renderMode,会添加到 pagelet 标签的 data-rm
属性和 pagelet 对象的 renderMode 属性
{pagelet id="mypagelet"}
<p>我是一个 pagelet</p>
<p>我能被单独加载和渲染</p>
{/pagelet}
上面的代码在 First
请求模式下输出:
<div id="mypagelet"></div>
<code id="__cnt_mypagelet" style="display:none"><!--
<p>我是一个 pagelet</p>
<p>我能被单独加载和渲染</p>
--></code>
<script>
BigPipe.setResourceMap({'xxx ResourceMap'});
BigPipe.onPageletArrive({
"id":"mypagelet",
"children":[],
"renderMode":"default",
"parent":null,
"deps":{
"beforedisplay":[],
"load":[]
},
"hooks":{}
});
</script>
在 Quickling
请求模式下,将输出
[
{
"id": "mypagelet",
"children": [ ],
"renderMode": "quickling",
"parent": "container",
"html": {
"html": "<p>我是一个 pagelet</p>
<p>我能被单独加载和渲染</p>"
},
"deps": {
"beforedisplay": []
},
"quickling": true,
"resourceMap": {},
"session": 0
}
]
Her 会根据优化策略适时的将 html 片段插入节点中,并且保证 CSS、JS 的加载和执行顺序。
{script}
{/script}
标签用来标注并收集页面中的代码片段。在输出时,Her 会将收集的代码封装成函数并且自动控制调用时机。
参考代码执行时机(TODO)
{script}
标签支持 pagelet-on
属性,用来控制脚本执行的时机。默认为 "load"
,即 pagelet 的HTML加载后执行。其他可选的值和对应的执行时机如下:
- arrive: pagelet 数据块到达时 (暂未实现)
- beforeload: pagelet 开始加载依赖的CSS/JS资源之前 (暂未实现)
- cssresolved: 依赖的css资源加载完成后 (暂未实现)
- beforedisplay: 显示(innerHTML)之前
- display: 显示之后
- jsresolved: 依赖的js资源加载完成后 (暂未实现)
- load: 加载完成
- afterload: 加载完成后 (暂未实现)
- beforeunload: 卸载之前
- unload: 卸载时
- afterunload: 卸载后 (暂未实现)
为了方便代码压缩和减少转义引起的BUG,{script}
标签还支持类似 var-varName=$smartyData
参数,Her 会自动将模板变量通过 json_encode 转义并且赋值给 varName
变量,方便直接引用。 (暂未实现)
注意:{script}
标签内不能再使用 Smarty 模板变量
为了方便开发时语法高亮,Her 在编译阶段引入了对 <script runat="server"(暂定)>
的预处理。
{$name="我是含有引号( ' )的用户名"}
<script runat="server" pagelet-on="beforeload" var-userName=$name>
var xxx = require(xxx);
xxx.XXX();
alert(userName);
</script>
上面的写法等同于:
{$name="我是含有引号( ' )的用户名"}
{script pagelet-on="beforeload" var-userName=$name}
var xxx = require(xxx);
xxx.XXX();
alert(userName);
{/script}
运行时代码会变为:
<script>
BigPipe.hooks["系统管理的ID"] = function(require, pagelet){
var userName = "我是含有引号( \' )的用户名";
var xxx = require(xxx);
xxx.XXX();
alert(userName);
};
</script>
{require}
标签用来标注一个资源依赖。可以用于 CSS 和 Js 资源, resourcePath
为资源路径:
{require name="common:js/jquery.js"}
{require name="common:css/color.css"}
{define}
标签用来定义一个可重用模板片段,该片段可以通过 {widget}
标签调用:
{*common:widget/title/title.tpl*}
{define userName="默认用户名"}
<!-- 一个可以重用的用户名显示组件 -->
<dl>
<dt>姓名</dt>
<dd>{$userName|escape}</dd>
</dl>
{/define}
{*调用方式如下:*}
{widget name="common:widget/title/title.tpl" userName="张三"}
为了方便在一个文件中定义逻辑相关的多个片段,{define}
和 {widget}
还支持 method
参数(默认为 "__main"
):
{*common:widget/title/title.tpl*}
{define method="showName" userName="默认用户名"}
<!-- 一个可以重用的用户名显示组件 -->
<dl>
<dt>姓名</dt>
<dd>{$userName|escape}</dd>
</dl>
{/define}
{*调用方式如下:*}
{widget name="common:widget/title/title.tpl" method="showName" userName="张三"}
{widget}
标签用来调用用 {define}
定义的可重用的模板片段。
参考{define}
标签