使用Handlebars模块化你的页面
Handlebars的layout和partials
Handlebars的layout文件和partials文件,可以是我们很轻松的组织一些公共的页面或代码片段,使得前端视图可维护性非常高。
Handlebars的layout文件
Express+express-handlebars项目中,我们定义好页面的layout文件后,然后在内容变化的位置加入{{{body}}}
,这样我们每次渲染页面都会替换到{{{body}}}
中,这种“布局文件”的概念大大的降低了我们的维护成本。
Handlebars的partials文件
partials文件,也就是片段文件,可以放置公共的引用。
在配置Handlebars的时候,我们可以指定partials文件目录:
var hbs = exphbs.create({
partialsDir: 'views/partials',
layoutsDir: "views/layouts/",
defaultLayout: 'main',
extname: '.hbs',
helpers: hbsHelper
});
这样在partials
目录下定义的handlebars文件都会是partials文件,使用方法:{{> head}}
。
下面是一个布局文件(layout.hbs),同时使用了partials文件,可供参考:
<!doctype html>
<html>
<head>
{{> head}}
</head>
<body class="hold-transition skin-blue layout-top-nav">
<div class="wrapper">
{{>header}}
<!-- Full Width Column -->
<div class="content-wrapper">
<div class="container">
{{{body}}}
</div>
</div>
</div>
{{>footer}}
<script src="/js/app.js"></script>
</body>
</html>
使用Helper实现段落功能
所谓段落功能,就是我们在页面预置一个位置,动态来渲染这个位置的代码(代码可以是html、js、或者css)。
概念听起来可以有些模糊,我们举个例子:
举个栗子
我们已经知道,上面的layout.hbs
文件是一个布局文件,所有的跳转页面都会通过这个布局文件来渲染内容,那么现在假如有一个个例页面(/hello
请求渲染的页面),需要用js来处理一段代码呢?
<script>
alert('hello world');
</script>
如果我们在layout中加入这段js代码,那么所有的页面都会打印hello world
,显然不是我们想要的,我们仅仅是想在请求/hello
的时候打印。
用partials?可以吗?答案是不可以。
partials仅能来组织公共的代码片段,不是用来个性化的。
那么又有童靴提出解决方案:在/hello
渲染的页面底下加上不就行了吗?
如:hello.hbs
这也是一种解决方案,但是出来的代码不伦不类,查看/hello
渲染的页面源码:
```javascript
<!doctype html>
<html>
<head>
{{> head}}
</head>
<body class="hold-transition skin-blue layout-top-nav">
<div class="wrapper">
{{>header}}
<!-- Full Width Column -->
<div class="content-wrapper">
<div class="container">
<script>
alert('hello world');
</script>
</div>
</div>
</div>
{{>footer}}
<script src="/js/app.js"></script>
</body>
</html>
我们的script代码片段跑到container
里了!这个简单的例子能满足需求,但是加入javascript片段依赖jquery,而jquery是在{{>footer}}
里引用呢?这里肯定就会报错了。
使用Helper优雅的解决段落问题
Handlebars提供了强大的Helper支持,使我们解决这个问题变得简单明了。
首先我们定义一个helper,来组织这些个性片段(这些片段可能包含js、css、特殊的html等等)。
section: function(name, block){
if(!this._sections) this._sections = {};
this._sections[name] = block.fn(this);
return null;
},
在这个helper 中,我们定义了_sections
变量(需要理解handlebars中的this关键字),当指定了_sections
的name
时,就会动态渲染session
中的内容。
如何使用?
首先我们可以在layout中预置一个section。如果我们渲染动态的js段落,需要放到{{> footer}}
下面。以下是改造后的layout文件部分代码:
{{>footer}}
<script src="/js/app.js"></script>
{{{_sections.js}}}
</body>
</html>
说明:
{{{_sections.js}}}
这段是预置的代码,意思是从this._sections
变量中取name
为js
的段落,渲染在这里。如果当前页面没有js
则不渲染。
位置预置好了,我们就可以写具体的段落了。接上个例子,只想在请求/hello
页面中打印hello world
,就可以在hello.hbs
中任意位置加入下面段落(最好是在页面最底下,方便维护)。
{{#section 'js'}}
<script>
alert('hello world')
</script>
{{/section}}
这样当我们请求/hello
时,就会打印hello world
,请求其他页面则不会有这段js代码。
养成良好的代码组织能力,有助于提高我们的编码质量!