使用Handlebars模块化你的页面
发布于 8 年前 作者 gefangshuai 11211 次浏览 来自 分享

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渲染的页面源码:

<!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关键字),当指定了_sectionsname时,就会动态渲染session中的内容。

如何使用? 首先我们可以在layout中预置一个section。如果我们渲染动态的js段落,需要放到{{> footer}}下面。以下是改造后的layout文件部分代码:

{{>footer}}
<script src="/js/app.js"></script>
{{{_sections.js}}}
</body>
</html>

说明:{{{_sections.js}}}这段是预置的代码,意思是从this._sections变量中取namejs的段落,渲染在这里。如果当前页面没有js则不渲染。

位置预置好了,我们就可以写具体的段落了。接上个例子,只想在请求/hello页面中打印hello world,就可以在hello.hbs中任意位置加入下面段落(最好是在页面最底下,方便维护)。

{{#section 'js'}}
    <script>
        alert('hello world')
    </script>
{{/section}}

这样当我们请求/hello时,就会打印hello world,请求其他页面则不会有这段js代码。

养成良好的代码组织能力,有助于提高我们的编码质量!

欢迎更多关注:http://www.jianshu.com/users/3b5b888d7697

3 回复

hbs比jade还是有点弱的

React 轻松模块化实现组件复用, 轻松过滤掉插入的 XSS 内容, 三种以上的语法任你选择~

可以试试 swig

回到顶部