资讯专栏INFORMATION COLUMN

Handlebars partials 隐藏的力量

sixleaves / 1709人阅读

摘要:和再来分别看看每个文件文件首先是有些值得注意的地方,拆开来多带带看引入了一个虚构的。部分我们又用了,不同的是我们用了基本来指定默认内容。文件拼图的下一部分就是。我们也用到了,同时还有,下面是的示例同样拆开来看看这里又用到了。

一个项目的机会再加上我自己的探索,让我对Handlebars partials有了更深的理解。事实证明,你可以做得比我了解的更多。

我最近在负责一个小项目,只有很少的静态页面。因为太小了,我们最开始没有使用模板系统。当项目开始往深一层推进时,我们发现把静态页面拆分成partials & layout的模板明显更好。

我们以前用过handlebars-layouts并且很喜欢它提供的那些特性。我本来想同时安装Handlebars和handlebars-layouts,但是又感觉过于累赘了。

我在想有没有可能只使用Handlebars而不用额外的handlebars-layouts库?

我并不是想吐槽handlebars-layouts,我们以后可能还会用到这个项目。但是我想试试只用Handlebars partials来实现一些handlebars-layouts通过helper来实现的一些特性。

花了一些时间来评估项目需求后我问自己:handlebars-layouts helpers提供的哪些特性是我需要的?根据过去的经验,我列出了如下helpers:

{{#extend}} layouts的能力

{{#embed}} partials的能力

能像{{#block}} 和 {{#content}}一样配合

列出来后,我开始查Handlebars partials文档来看看行不行。然后我发现我从来没有利用到partials的全部潜力,只要做一点小小的努力就可以让它们实现我的需求。有两个特性吸引了我:partial blocks和inline partials。

我兴奋地意识到Handlebars partials可以做到比我想象中多得多的事情并马上开始了工作。

Partials基础

在开始前,还是先看一看基本partials, partial blocks 和 inline partials。

基本partials就像这样:

{{> content-block }}

它会试图找到一个命名为content-block的partial进行渲染,否则就报错。

Handlebars partial的文档上写:

The normal behavior when attempting to render a partial that is not found is for the implementation to throw an error. If failover is desired instead, partials may be called using the block syntax.

渲染一个partial的默认行为是,如果没找到就报错。如果要进行错误处理,就要用block的方式来使用。

partial block就像这样:

{{#> content-block}}
  Default content
{{/content-block}}

这样写有一个好处,就是当content-block没有找到时,partial block里面的部分就会被渲染,像上面就会渲染“Default content”。

而inline partial就像这样:

{{#*inline "content-block"}}
  My new content
{{/inline}}

文档里是这样说的:

Templates may define block scoped partials via the inline decorator.

通过使用inline修饰符,可以在模板中定义块级partials。

inline partial允许你临时创建partials。如果页面中有一个content-block partial block,然后我们创建了content-block inline partial的话,inline partial中的内容(“My new content”) 就会替换partial block中默认内容。inline partial同样可以替换基本partials,只是基本partials没有默认内容而已。

了解完这些后我们就可以开始了。

目录结构

我想同时拥有layouts/includes/pages/,目录结构看起来如下:

src/
├── pages
│   ├── page-one.hbs
│   └── page-two.hbs
└── partials
    ├── includes
    │   ├── hero.hbs
    │   └── footer.hbs
    └── layouts
        └── base.hbs

为了进行渲染使用了Gulp + gulp-compile-handlebars,在htmlgulp任务中把src/pages/*.hbs当成source目录,就像下面这样:

// gulpfile.js

const handlebars = require("gulp-compile-handlebars");
const rename = require("gulp-rename");

gulp.task("html", () => {
  return gulp.src("./src/pages/*.hbs")
    .pipe(handlebars({}, {
      ignorePartials: true,
      batch: ["./src/partials"]
    }))
    .pipe(rename({
      extname: ".html"
    }))
    .pipe(gulp.dest("./dist"));
});

需要注意,我们口中的“page”, “include”和“layout”,本质上都是Handlebars partial,这就是保证可扩展性的关键。一旦了解了这个,新世界的大门就打开了。

Layouts, pages 和 includes

再来分别看看每个文件:

Layouts 文件

首先是layouts/base.hbs

{{!-- layouts/base.hbs --}}



  
    
      {{#if title}}
        {{title}}
      {{else}}
        Base Page Title
      {{/if}}
    
    
    {{#> head-block}}
      {{!-- Custom  content per page could be added. --}}
    {{/head-block}}
  
  
    {{#> hero-block}}
      {{!-- Hero content goes here. --}}
    {{/hero-block}}

    
{{#> footer-block}} {{!-- The `includes/footer` partial is the default content, but can be overridden. --}} {{> includes/footer }} {{/footer-block}}
{{#> scripts-block}} {{!-- Custom scripts per page can be added. --}} {{/scripts-block}}

有些值得注意的地方,拆开来多带带看:


{{#> head-block}}
  {{!-- Custom  content per page could be added. --}}
{{/head-block}}

引入了一个虚构的main.css。然后设置了head-block,当一个具体的page继承此layout时在这里传入中的内容(注:就跟handlebars-layouts的{{#block}} helper一样)。

{{#> hero-block}}
  {{!-- Hero content goes here. --}}
{{/hero-block}}
{{#> scripts-block}}
  {{!-- Custom scripts per page can be added. --}}
{{/scripts-block}}

head-block一样,我们在hero和scripts部分都用了Handlebars partial blocks。在同一套模板有不同的内容和scripts的时候,显得更加灵活。

{{#> footer-block}} {{!-- The `includes/footer` partial is the default content, but can be overridden. --}} {{> includes/footer }} {{/footer-block}}

footer部分我们又用了Handlebars partial block,不同的是我们用了{{> includes/footer }}基本partial来指定默认内容。

footer-block没有被传入内容时就会渲染默认内容。所有代码中,我们都用的Handlebars注释(注:这些注释不会被渲染到HTML中,如果你用HTML注释就会被渲染到HTML中,因为partial block中所有内容都会被渲染)。

page 文件

拼图的下一部分就是page partial。我们也用到了Handlebars partial blocks,同时还有Handlebars inline partials,下面是pages/page-one.hbs的示例:

{{!-- pages/page-one.hbs --}}

{{#> layouts/base title="Page One" }}

  {{#*inline "hero-block"}}
    {{> includes/hero
      hero-src="img/hero-1.png"
      hero-alt="Hero 1 alt title"
    }}
  {{/inline}}

{{/layouts/base}}

同样拆开来看看:

{{#> layouts/base title="Page One" }}
  ...
{{/layouts/base}}

这里又用到了Handlebars partial block。但是这次,我们用它来继承layouts/base(注:就跟handlebars-layouts {{#extend}} helper一样),同时设置了page的title(注:用到了partial 参数特性)。

{{#*inline "hero-block"}}
  ...
{{/inline}}

这是我们第一次用到Handlebars inline partial。这个inline partial被传入layouts/base然后被其中的hero-block注入(注:用法就跟 handlebars-layouts 的 {{#content}} helper 一样)。

{{> includes/hero
  hero-src="http://fpoimg.com/500x200"
  hero-alt="Hero 1 alt title"
}}

最后我们引入indludes/hero基本partial(注:就跟handlebars-layouts {{#embed}} helper一样)。

includes 文件

includes/*.hbs可以被layouts 和 pages引用。既然都用到了,那就看看大概是什么样子的:

{{!-- includes/hero.hbs --}}

没什么开创性的东西,只是简单地渲染传入的hero-srchero-alt(注:可以改进的地方:用{{#if}}{{else}}来判断参数是否为空)。

再看看includes/footer.hbs

{{!-- includes/footer.hbs --}}

This is some default footer content.

没啥特别的,这就是layouts/base中footer的默认内容。

最后成果

来概括一下所有东西。

layouts/base.hbs

充当基础layout文件

使用partial blocks定义默认和动态内容

pages/page-one.hbs

充当page文件

使用partial block来继承基本layout

使用inline partials填充内容到layout中的 partial blocks

includes/*.hbs

partials可以被 layouts 或 pages 引用

可以在partial block或inline partial中使用

然后就是最后渲染出的page-one.html文件,看起来就是这样:





  
    Page One
    
    
  
  
    
    

This is some default footer content.

让我们再试试使用同一个layout,但改一些东西,就叫它pages/page-two.hbs好了:

{{!-- pages/page-two.hbs --}}

{{#> layouts/base title="Page Two" }}

  {{!-- Let"s add a second stylesheet for this layout. --}}
  {{#*inline "head-block"}}
    
  {{/inline}}

  {{!-- Let"s change the hero image for this layout. --}}
  {{#*inline "hero-block"}}
    {{> includes/hero
      hero-src="http://fpoimg.com/400x400"
      hero-alt="Hero 2 alt title"
    }}
  {{/inline}}

  {{!-- Let"s override the "footer-block" content. --}}
  {{#*inline "footer-block"}}
    

We are now overriding the default "footer-block" content with this content.

{{/inline}} {{!-- Let"s add a script for this layout. --}} {{#*inline "scripts-block"}} {{/inline}} {{/layouts/base}}

渲染出来就是这样:





  
    Page Two
    
    
    
  
  
    
    

We are now overriding the default "footer-block" content with this content.

这样我们就用同一个layout渲染出了两个不同的页面。

感谢

我们用Handlebars 的partial blocks, inline partials, basic partials 和partial parameters模拟出了handlebars-layouts的{{#extend}, {{#embed}}, {{#block}} 和 {{#content}} helpers。

这是一次有趣的尝试,让我更好地理解了Handlebars partials。注意在不同的项目中,我们必须先评估库提供的特性,有哪些是需要的,哪些是不需要的,没有一个完美的解决方案(注:有些特性是无法模拟的,比如 {{#content}} 的 append 和 prepend,又比如content作subexpression时,用conditonal blocks 检查content是否为空)。

如果你想要了解更多,可以看看这个项目,试试各种组合,看看能不能挖掘出更多的Handlebars partials的潜力。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97736.html

相关文章

  • 如何实现一个脚手架进阶版(Vue-cli v2.9学习篇)

    摘要:如果没有看过之前一篇博客的,或者对的脚手架没有了解过的同学,推荐先看上一篇如何实现一个简单的脚手架。它是一个用来构建静态网站的类库,也能够用来对文件进行处理。有任何问题欢迎进行交流。 前言 在之前一篇博客介绍了关于Node脚手架的一些基础的知识,这篇博客是在之前的基础上针对在Node中开发脚手架中遇到的问题,如: 终端样式、交互问题 文件处理问题 通过对Vue-cli 2.9.2的...

    thekingisalwaysluc 评论0 收藏0
  • 用express搭建网站

    摘要:先建个简单的服务器当然你先得安装使用,如果这里的代码复制后运行不了请移步我的下载源码顺手给我个小星星鼓励哈运行后访问默认匹配的路由是,多个要使用方法,但是使用了,或者就不能使用到达下一个了是添加路由的方法,忽略大小写,反斜杠,进行匹配时不 先建个简单的服务器 当然你先得安装express npm install express //使用express,如果这里的代码复制后运行不了请移步...

    Kosmos 评论0 收藏0
  • Handlebars模板部署时发布为预编译过模板函数

    摘要:静态模板文件的内容,如模板等,多为字符串,如果直接部署上线,则需要在线上实时编译,引入的模板引擎也需要包含编译的部分。如果部署时之前先进行模板预编译,则模板文件内容为一个预编译后生成的模板函数。使用进行预编译,有几种方式。 静态模板文件的内容,如 Handlebars模板等,多为字符串,如果直接部署上线,则需要在线上实时编译,引入的模板引擎也需要包含编译的部分。 如果部署时之前先进行...

    SnaiLiu 评论0 收藏0
  • Handlebars—semantic template engine

    摘要:维护起来将是我们开发的噩梦。的都是这种的闭合结构的判断只能判断和,没办法进行这种的逻辑判断。它的设定就是如此,它认为逻辑判断的内容不应该出现在模板中。因为的输出默认转义,几乎所有的模板引擎输出默认都是转义的,避免攻击。 概述 刚接触前端的时候,师傅就给我推荐了Handlebars,自己也蛮喜欢它的语法。到现在,Handlebars都已经更新到3.0.3了,是时候重新过一遍文档了。 ...

    cyrils 评论0 收藏0
  • 环境搭建以及使用Ember.js创建第一个静态页面

    摘要:原文环境搭建以及使用创建第一个静态页面本篇将为读者介绍项目开发环境的搭建,并创建一个静态页面。在文件中增加如下内容使用快捷键关闭在用命令启动项目。创建一个模板仍然是使用命令创建模板。 原文:环境搭建以及使用Ember.js创建第一个静态页面 本篇将为读者介绍Ember项目开发环境的搭建,并创建一个静态页面。 安装Ember CLI 本教程使用的是2.4.3版本的Ember CLI工具集...

    pinecone 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<