落实后端组件化,模板引擎从前后端用法

行使 handlebars 完毕后端组件化

2016/04/27 · 基本功技术 ·
handlebars,
组件化

本文作者: 伯乐在线 –
亚里士朱代珍
。未经作者许可,禁止转发!
欢迎参预伯乐在线 专栏撰稿人落实后端组件化,模板引擎从前后端用法。。

基本声明(使用过exress和handlebars的可以略过):express中的handlebars引擎是这么生成页面的:

XHTML

/* layout.hbs *
主模板,所有的的页面都将替换”{{{body}}}”,”{{}}”约等于占位符,由数量开展沟通
*/ <!DOCTYPE html> <html> <head>
<title>{{title}}</title> </head> <body>
{{{body}}} </body> </html> /* index.hbs *
单个页面模板,那里以首页为例。”{{>}}”表示援引其余模板来替换,那里引用名为”partial”的模版
*/ <div>index</div> {{>partial}} /* partial.hbs *
一个分页文件,被其余模板引用,分页之间也足以互相引用。 */
<div>123</div> /* index.html *
当浏览器请求index.html时,经过handlebars模板引擎处理后转变的页面 */
<!DOCTYPE html> <html> <head>
<title></title> </head> <body>
<div>index</div> <div>123</div> </body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* layout.hbs
* 主模板,所有的的页面都将替换"{{{body}}}","{{}}"相当于占位符,由数据进行替换
*/
<!DOCTYPE html>
<html>
  <head>
    <title>{{title}}</title>
  </head>
  <body>
    {{{body}}}
  </body>
</html>
 
/* index.hbs
* 单个页面模板,这里以首页为例。"{{>}}"表示引用其他模板来替换,这里引用名为"partial"的模板
*/
<div>index</div>
{{>partial}}
 
/* partial.hbs
* 一个分页文件,被其他模板引用,分页之间也可以互相引用。
*/
<div>123</div>
 
/* index.html
* 当浏览器请求index.html时,经过handlebars模板引擎处理后生成的页面
*/
<!DOCTYPE html>
<html>
   <head>
     <title></title>
   </head>
   <body>
     <div>index</div>
     <div>123</div>
   </body>
</html>

复制代码 代码如下:

前言

无意间,居然已经这么久没有写博客了,坚定不移还真是世界上最难的事情啊。

只是自己近年也没闲着,辞工换工、恋爱失恋、布里斯班京城都经历了一番,那有起有落的生存实在是太刺激了,似乎拿着两把菜刀剁洋葱一样,想想就泪流满面。

弃我去者、前几天之日不可留,乱我心者、明天之日多烦忧,仍然说说近年来触及到的模板引擎
Handlebars 吧。

print?<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“; 
<html xmlns=”; 
<head> 
    <title>YanCms左边导航栏</title> 
    <script src=”js/jquery-1.4.2.min.js”
type=”text/javascript”></script> 
    <script src=”js/jquery-ui-1.8.custom.min.js”
type=”text/javascript”></script> 
    <script type=”text/javascript”> 
        $(document).ready(function () { 
            //#title代表页面中点击的因素 
            $(“.title”).click(function () { 
                var con = $(this).html(); 
                //#getTitle代表页面中想要获得title的值元素 
                $(“#getTitle”).html(con); 
                //$(this).attr(‘href’)获取超链接 
                var con1 = $(this).attr(‘href’); 
               // $(“#getTitle”).attr(“href”, “con1”); 
               // alert(con1); 
            }); 
        }); 
   </script> 
    <script type=”text/javascript”> 
        jQuery().ready(function () { 
            jQuery(“#navigation”).accordion({ 
                header: ‘.head’, 
                event: ‘click’, 
                fillSpace: true, 
                animated: ‘bounceslide’ 
            }); 
        }); 
    </script> 
    <link href=”css/left.css” rel=”stylesheet” type=”text/css”
/> 
    </head> 
<body style=”background-color:#e6f4fa;” > 
        <div class=”subMenuTitle” id=”getTitle”><a
href=”#”>主成效菜单</a></div> 
        <div style=”height:100%;”> 
            <ul id=”navigation”> 
                <li> 
                    <a class=”head”>体系管理</a> 
                    <ul> 
                        <li class=”title”> 
                            <a href=”#1233333″
>博文列表</a> 
                        </li> 
                         
                        <li class=”title”> 
                            <a href=”#”>添加博文</a> 
                        </li> 
                    </ul> 
                </li> 
                <li> 
                    <a class=”head”>系列管理</a> 
                    <ul> 
                        <li> 
                            <a href=”#” target=”rightFrame”>
连串列表</a> 
                        </li> 
                    </ul> 
                </li> 
                <li> 
                    <a class=”head”>友情链接</a> 
                    <ul> 
                        <li> 
                            <a href=”#” target=”rightFrame”>
链接列表</a> 
                        </li> 
                        <li> 
                            <a href=”#”
target=”rightFrame”>添加链接</a> 
                        </li> 
                         
                    </ul> 
                </li> 
                <li> 
                    <a class=”head”>系统管理</a> 
                    <ul> 
                        <li> 
                            <a href=”#”
target=”rightFrame”>修改管理员密码</a> 
                        </li> 
                         
                     
                    </ul> 
                </li> 
                 
                <li> 
                    <a class=”head”>权限管理</a> 
                    <ul> 
                        <li> 
                            <a href=”#”
target=”rightFrame”>暂未开放</a> 
                        </li> 
                        <li> 
                            <a href=”#”
target=”rightFrame”>暂未开放</a> 
                        </li> 
                         
                     
                    </ul> 
                     
                </li> 
            </ul> 
        </div> 
        
    </body> 
</html> 

心想事成步骤1:模板

react的火热让“组件化”的定义持续升温,然则组件化确实在付出中提供了高可复用的代码,大大收缩了工作量和bug,确实值得提倡。举个例子。

XHTML

<ul class=”titles border” id=”navigator”> <li
class=”title”>标题1</li> <li
class=”title”>标题2</li> <li
class=”title”>标题3</li> </ul>

1
2
3
4
5
<ul class="titles border" id="navigator">
  <li class="title">标题1</li>
  <li class="title">标题2</li>
  <li class="title">标题3</li>
</ul>

这一段html代码,会在多少个页面用到,就算根据一般的做法把那段代码ctrl-c、ctrl-v到要用的页面。就会现出多少个难点:1.重新代码增多(ctrl-c、ctrl-v应该是程序员的禁忌),当然这不是最重视的,最重视的是第2点——维护性差。如果现在本身要把“标题1”改成“标题0”,那么只可以举办全量搜索然后替换,不仅操作麻烦而且便于出错。
假设用到了模版技术的话那些题材就很好解决,把地点那一段代码写成一个模板,在handlebars中大家成为分页,然后需要这段的代码的页面引用这一个分页,要是要修改的话一向修改分页了。以handlebars为例:

XHTML

亚洲必赢官网,//navigator.hbs <ul class=”titles border” id=”navigator”> <li
class=”title”>标题1</li> <li
class=”title”>标题2</li> <li
class=”title”>标题3</li> </ul> //在index.hbs中引用
{{>navigator}}

1
2
3
4
5
6
7
8
9
//navigator.hbs
<ul class="titles border" id="navigator">
  <li class="title">标题1</li>
  <li class="title">标题2</li>
  <li class="title">标题3</li>
</ul>
 
//在index.hbs中引用
{{>navigator}}

干什么handlebars?本文所用的后端模板引擎都以handlebars为例,原因是上次听去何方前端团队做的有关node.js的技术分享,炫耀了一个投机按照handlebars完毕的小功能:分页中援引的css文件能够整个放权head中。心中一向觊觎那一个小效用,直到日前和“组件化”的定义结合在一齐考虑,发现这么些成效对于完结后端的组件化很有扶助。自己对handlebars也略有商讨,所以试着用handlebars来贯彻一下“组件化”。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“;
<html xmlns=”;
<head>
    <title>YanCms左边导航栏</title>
    <script src=”js/jquery-1.4.2.min.js”
type=”text/javascript”></script>
    <script src=”js/jquery-ui-1.8.custom.min.js”
type=”text/javascript”></script>
    <script type=”text/javascript”>
        $(document).ready(function () {
            //#title代表页面中点击的因素
            $(“.title”).click(function () {
                var con = $(this).html();
                //#getTitle代表页面中想要得到title的值元素
                $(“#getTitle”).html(con);
                //$(this).attr(‘href’)获取超链接
                var con1 = $(this).attr(‘href’);
               // $(“#getTitle”).attr(“href”, “con1”);
               // alert(con1);
            });
        });
   </script>
    <script type=”text/javascript”>
        jQuery().ready(function () {
            jQuery(“#navigation”).accordion({
                header: ‘.head’,
                event: ‘click’,
                fillSpace: true,
                animated: ‘bounceslide’
            });
        });
    </script>
    <link href=”css/left.css” rel=”stylesheet” type=”text/css”
/>
    </head>
<body style=”background-color:#e6f4fa;” >
        <div class=”subMenuTitle” id=”getTitle”><a
href=”#”>主作用菜单</a></div>
        <div style=”height:100%;”>
            <ul id=”navigation”>
                <li>
                    <a class=”head”>序列管理</a>
                    <ul>
                        <li class=”title”>
                            <a href=”#1233333″
>博文列表</a>
                        </li>

Handlebars 简介

先引用下百科的传道:

style=”font-size: 16px; font-family: ‘Microsoft YaHei’;”>Handlebars 是
JavaScript
一个语义模板库,通过对view和data的诀别来很快打造Web模板。它选拔”Logic-less
template”(无逻辑模版)的思绪,在加载时被预编译,而不是到了客户端执行到代码时再去编译,
那样可以确保模板加载和运作的快慢。

好啊,看了多少懵闭。那里紧要词就是七个:无逻辑、预加载。所有的模版引擎都是view和data分离,那点并非说。无逻辑准确点来说应该是弱逻辑,毕竟里面或者有局地if、each逻辑在的。你也许看过众多那样写的模板语言:

1 <% if (names.length) { %>
2   <ul>
3     <% names.forEach(function(name){ %>
4       <li><%= name %></li>
5     <% }) %>
6   </ul>
7 <% } %>

注:闭合的大括号一定毫无忘了写哦。

看那种 js
与 HTML
的杂交写法我以为很眼疼,我的眼里代码的可读性是尤其关键的,那种写法真不是自身的那杯茶!可是那种模板技术的达成格局倒是值得一探,推荐看看这么些20行代码的沙盘引擎完毕:,挺有意思的做法,当然用eval也足以做。


Handlebar 的语法就概括精练了千千万万,比如下边的可以写成:

1 {{#if names.length}}
2   <ul>
3     {{#each names}}
4       <li>{{this}}</li>
5     {{/each}}
6   </ul>
7 {{/if}}

就喜欢那种一目了解的觉得,当然还有其余的swig、tx出的art-template之类的沙盘引擎,萝卜青菜各有所爱,就不多说了。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“;
<html xmlns=”;
<head>
    <title>YanCms左侧导航栏</title>
    <script src=”js/jquery-1.4.2.min.js”
type=”text/javascript”></script>
    <script src=”js/jquery-ui-1.8.custom.min.js”
type=”text/javascript”></script>
    <script type=”text/javascript”>
        $(document).ready(function () {
            //#title代表页面中点击的要素
            $(“.title”).click(function () {
                var con = $(this).html();
                //#getTitle代表页面中想要得到title的值元素
                $(“#getTitle”).html(con);
                //$(this).attr(‘href’)获取超链接
                var con1 = $(this).attr(‘href’);
               // $(“#getTitle”).attr(“href”, “con1”);
               // alert(con1);
            });
        });
   </script>
    <script type=”text/javascript”>
        jQuery().ready(function () {
            jQuery(“#navigation”).accordion({
                header: ‘.head’,
                event: ‘click’,
                fillSpace: true,
                animated: ‘bounceslide’
            });
        });
 </script>
    <link href=”css/left.css” rel=”stylesheet” type=”text/css”
/>
 </head>
<body style=”background-color:#e6f4fa;” >
        <div class=”subMenuTitle” id=”getTitle”><a
href=”#”>主作用菜单</a></div>
  <div style=”height:100%;”>
   <ul id=”navigation”>
    <li>
     <a class=”head”>序列管理</a>
     <ul>
      <li class=”title”>
       <a href=”#1233333″ >博文列表</a>
      </li>
      
      <li class=”title”>
       <a href=”#”>添加博文</a>
      </li>
     </ul>
    </li>
    <li>
     <a class=”head”>连串管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”> 序列列表</a>
      </li>
        </ul>
    </li>
    <li>
     <a class=”head”>友情链接</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”> 链接列表</a>
      </li>
      <li>
       <a href=”#” target=”rightFrame”>添加链接</a>
      </li>
      
     </ul>
    </li>
    <li>
     <a class=”head”>系统管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”>修改管理员密码</a>
      </li>
      
     
     </ul>
    </li>
    
    <li>
     <a class=”head”>权限管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”>暂未开放</a>
      </li>
      <li>
       <a href=”#” target=”rightFrame”>暂未开放</a>
      </li>
      
     
     </ul>
     
    </li>
   </ul>
  </div>
      
 </body>
</html>

兑现步骤2:打包

诸如此类就全盘了么?no~no~no~
上面的这一段html代码中不过有体制的,按照w3c的正统,样式应该写在css文件中,怎么落实?任其自然想到三种解决办法:

  1. 在分页中参预link标签来引入所需的体裁,想一想html代码中遍地穿插link标签是何许感觉~且不说生成页面难以保险,浏览器渲染速度也会受影响。
  2. 把分页所需的样式放在公共的体制文件中,那是时下大家项目标通用做法,纯粹的懒人策略,缺点很扎眼,很多页面引用了有些不行的体制,浪费互联网带宽,尤其当项目变大时以此毛病将越是肯定。
    所以最好的化解方法是按需加载,只加载引用组件所需的体裁,当然样式文件按分页拆分得这般细的话会大增请求数,影响不会太大,如果想优化的话也足以减掉合并成一个请求,那些前面再说。
    handlerbas中普遍的扩大方式就是编制helper,大家得以编制一个helper,

XHTML

//app.js hbs.registerHelper(‘css’, function(str, option) {
//在上下文中创设一个数组用来保存该页面须要使用的css文件 this.cssList =
this.cssList || []; this.cssList.push(str); });

1
2
3
4
5
6
//app.js
hbs.registerHelper(‘css’, function(str, option) {
  //在上下文中创建一个数组用来保存该页面需要用到的css文件
  this.cssList = this.cssList || [];  
  this.cssList.push(str);
});

以此helper的法力就是挂号一个名为”css”的helper,帮大家保留分页中用到的css文件地方。然后我们在主模板layout的head标签部分遍历cssList数组循环加载出来。

XHTML

//layout.hbs <head> <title>{{title}}</title> {{#each
cssList}} <link rel=”stylesheet” href=”{{this}}” media=”screen”
title=”no title” charset=”utf-8″> {{/each}} </head> …

1
2
3
4
5
6
7
8
9
//layout.hbs
<head>
  <title>{{title}}</title>
 
  {{#each cssList}}
  <link rel="stylesheet" href="{{this}}" media="screen" title="no title" charset="utf-8">
  {{/each}}
</head>

与此同时原来的分页改成

XHTML

//navigator.hbs {{css ‘/stylesheets/components/navigator.css’}} <ul
class=”titles border” id=”navigator”> <li
class=”title”>标题1</li> <li
class=”title”>标题2</li> <li
class=”title”>标题3</li> </ul>

1
2
3
4
5
6
7
//navigator.hbs
{{css ‘/stylesheets/components/navigator.css’}}
<ul class="titles border" id="navigator">
  <li class="title">标题1</li>
  <li class="title">标题2</li>
  <li class="title">标题3</li>
</ul>

地点写的只是一个概括的无逻辑的静态组件,有些组件可能会有相互功效,比如拍卖部分点击事件或者对外暴光可操作的接口等,那么就要求js逻辑来完毕了。

                        <li class=”title”>
                            <a href=”#”>添加博文</a>
                        </li>
                    </ul>
                </li>
                <li>
                    <a class=”head”>体系管理</a>
                    <ul>
                        <li>
                            <a href=”#” target=”rightFrame”>
体系列表</a>
                        </li>
                    </ul>
                </li>
                <li>
                    <a class=”head”>友情链接</a>
                    <ul>
                        <li>
                            <a href=”#” target=”rightFrame”>
链接列表</a>
                        </li>
                        <li>
                            <a href=”#”
target=”rightFrame”>添加链接</a>
                        </li>

语法基础

语法很简短,就是用大括号将
data 包裹起来。其中两个 {{}}
会将内容做HTML编码转换,那里你输入的HTML标签代码什么的都会按您输入的字符输出;而三个{{{}}}
的时候则不做转换,你在里头输入<h1>最终是真的能赢得一个h1标签的。其他一些规则要素分别有:

1)块级


Handlebars里面,每个#就象征了一个局地块,每个块都有自身的功用域范围。举例来说:

1 // 数据
2 hehe: { words: 'hehehehe' }
3 yoyo: { words: 'yoyoyoyo'}

对应的模版:

1 {{#hehe}}
2   <p>{{words}}</p>
3 {{/hehe}}
4 {{#yoyo}}
5   <p>{{words}}</p>
6 {{/yoyo}}

那几个事例很好掌握,words属性都是依照自己的对象来输出的。那里仍然根据块级成效域去通晓会相比较不难(即使js并从未块级成效域。。。),也可以用this来取代当前目的。注意,即便是#if、#each也是有作用域的,不要跟js中的功用范围模糊。

2)路径

对于目的的话,你可以坚守上文的事例一样一向运用
name 的 length
属性,仍能动用使用路径的表明形式去做客对象的任何层级。举个栗子:

 1 var post = {
 2   title: "Blog Post!",
 3   author: [{
 4     id: 47,
 5     name: "Jack"
 6   },{
 7     id: 20,
 8     name: "Mark"
 9   }]
10 };

模板要如此写:

 1 {{#post}}
 2   {{#if author.length}}
 3     <h3>{{title}}</h3>
 4     <ul>
 5       {{#each author}}
 6         <li>{{../title}}'s author is {{name}}</li>
 7       {{/each}}
 8     </ul>
 9   {{/if}}
10 {{/post}}

li标签里面已经是在
author 字段之内了,所以要选用 ‘../’ 来转到上层的 title。

3)helper

地方其实已经用过helper了,内置的helper有if、each、unless、with等,当然你也足以自己去写helper。由于Handlebar的弱逻辑属性,假使要贯彻复杂一点的逻辑就须求去自定义helper。举个栗子:

 1 //判断是否是偶数
 2 Handlebars.registerHelper('if_even', function(value, options) {
 3   console.log('value:', value); // value: 2
 4   console.log('this:', this); // this: Object {num: 2}
 5   console.log('fn(this):', options.fn(this)); // fn(this): 2是偶数
 6   if((value % 2) == 0) {
 7     return options.fn(this);
 8   } else {
 9     return options.inverse(this);
10   }
11 });

helper是这样用的:

1 {{#if_even num}}
2       {{this.num}}是偶数
3 {{else}}
4       {{this.num}}是奇数
5 {{/if_even}}

自然输出你也能想到,就是根据奇数偶数输出相应新闻。我们看看定义的一个function(value,
options){},那几个items就是大家应用模板时候的num,options是有些布局项,那里大家用到的是fn函数,这些函数执行的结果就是编译的结果(那里结果是“2是偶数”这一句话)。别的一个options.inverse就是取反,对应的就是模板里面的else语句了。

but:在模板中过度施用逻辑,实际上就是混淆了模版的专注点,那有违原本数据和显现分离的观点。我要么认为模板应该专注数据绑定,逻辑应该在数据层做预处理,然后将结果重回给模板,而不是让模板去做各个数据的演算。

4)partial

运用模板引擎最根本的一点就是使用其partial成效,Handlebars里面是听从注册再利用的法子来治本partial的。举个栗子:

1 Handlebars.registerPartial('userMessage',
2   '<{{tagName}}>By {{author.firstName}} {{author.lastName}}</{{tagName}}>'
3   + '<div class="body">{{body}}</div>'
4 );

应用的时候就可以直接行使{{>
userMessage}}将以此小块引入到页面中了。那里就是不难的一对替换,所以partial里面的data跟当前页面的data是在同顶尖的功用域内,也就是说你假如定义好author、body传进去就行了。tagName那一个属于表现层的变量,应该在hbs文件之中举办宣示,也即是{{>
userMessage tagName=”h1″ }}那样使用。

 

心想事成步骤3:逻辑

实在完结原理也开封小异,也是先挂号一个helper,然后在主模板layout中增加,那里大家在原来的分页中引入一个js文件。具体代码如下:

JavaScript

//app.js hbs.registerHelper(‘js’, function(str, option) { this.jsList =
this.jsList || []; this.jsList.push(str); });

1
2
3
4
5
//app.js
hbs.registerHelper(‘js’, function(str, option) {
  this.jsList = this.jsList || [];
  this.jsList.push(str);
});

XHTML

//layout.hbs … <body> {{{body}}} {{#each jsList}} <script
src=”{{this}}” charset=”utf-8″></script> {{/each}}
</body>

1
2
3
4
5
6
7
8
//layout.hbs
<body>
  {{{body}}}
  {{#each jsList}}
  <script src="{{this}}" charset="utf-8"></script>
  {{/each}}
</body>

XHTML

//navigator.hbs {{css ‘/stylesheets/components/navigator.css’}} {{js
‘/javascripts/components/navigator.js’}} <ul class=”titles border”
id=”navigator”> <li class=”title”>标题1</li> <li
class=”title”>标题2</li> <li
class=”title”>标题3</li> </ul>

1
2
3
4
5
6
7
8
//navigator.hbs
{{css ‘/stylesheets/components/navigator.css’}}
{{js ‘/javascripts/components/navigator.js’}}
<ul class="titles border" id="navigator">
  <li class="title">标题1</li>
  <li class="title">标题2</li>
  <li class="title">标题3</li>
</ul>

今昔早已达成将css、js、html封装成独立的机件了,不过尔尔依然有个难题。假如a组件引用了public.css和a.css文件,而b组件引用了public.css和b.css文件,那么依据地方的做法,会在head写八个一样的link标签,组件共同器重的文书越来越多,重复的竹签就越来越多。那当然不是我们所想看到的。

                    </ul>
                </li>
                <li>
                    <a class=”head”>系统管理</a>
                    <ul>
                        <li>
                            <a href=”#”
target=”rightFrame”>修改管理员密码</a>
                        </li>

在前者选用hbs

间接引入js的法门就不多说了,那里自己是接纳webpack来归并保管各个资源的。Handlebars对应的webpack插件为handlebars-loader,loader的布置分外不难:

1 { 
2   test: /\.hbs$/,
3   loader: "handlebars"
4 }

Handlebars的后缀有三种,全称的handlebars以及简称的hbs,也足以直接用html,但照旧跟普通html文件分别开来好一些。

利用模板的好处当然就是足以组件化开发了。我那边运用的目录是那样的:

亚洲必赢官网 1

个中页面组件指的是使用中的页面单元,页面是由各样控件组件组成的,那一个都曾经是共识了,就不再赘言了。引用的法门有两种:

(1)因为Handlebar编译出来的只是一个字符串,所以大家得以用js作为入口去管理组件,每个组件的js文件引入相应的css和模板,输出为dom字符串。页面引用组件的时候就直接引用js模块得到dom字符串,然后将dom字符串渲染到相应的{{{}}}中去。那种js大一统的艺术跟现在主流框架的做法是如出一辙的,可以将逻辑、样式、内容和资源集合起来管理,组件也得内聚性相比强。

 1 // header.js
 2 require('./header.scss');
 3 var headerTpl = require('./header.hbs');
 4 var data = {words: "This is header!"}; //data可以用参数传入
 5 var header = headerTpl(data);
 6 module.exports = header;
 7 
 8 // home.hbs
 9 <div class="home">
10   {{{ header }}}
11 <h2>This is {{name}} page.</h2>
12 {{{ footer }}}
13 </div>
14 
15 // home.js
16 require('./home.scss');
17 var header = require('../../component/header/header.js');
18 var footer = require('../../component/footer/footer.js');
19 var homeTpl = require('./home.hbs');
20 var data = {
21   header: header,
22   footer: footer,
23   name: 'home'
24 };
25 var home = homeTpl(data);
26 module.exports = home;

(2)
别的的方案就是行使一些模板的措施了,这种艺术对一些不带js逻辑的机件格外确切,比如页头页尾这一个纯内容的零件。在hbs里面可以直接根据路径去引用particle,然后把引入组件的时候提供partial所需的数额,例如home页面就是那样的:

<div class="home">
  {{> ../../component/header/header}}
  <h2>this is {{}} page</h2>
  {{> ../../component/footer/footer}}
</div>

既是大家曾经用了webpack来治本,当然也可以让webpack来拍卖引用路径了,那里只需求在布局内部注解partial的途径即可直接引用,loader配置:

 1 {
 2   test: /\.hbs$/,
 3   loader: "handlebars",
 4   query: {
 5     partialDirs: [
 6       path.join(SRC_PATH, 'component', 'header'),
 7       path.join(SRC_PATH, 'component', 'footer'),
 8       path.join(SRC_PATH, 'page', 'home')
 9     ]
10   }
11 }

模板文件:

<div class="home">
  {{> header }}
    <h2>This is {{name}} page.</h2>
  {{> footer }}
</div>

上边列出的二种方法各有优劣,使用partial的措施得以将相应的模板文件集中停放一个view文件夹里面,partialDirs就毫无写一大堆路径了。个人照旧更偏向于拔取第一种办法,每个组件的css、html、js文件做成一个完全的办法,遵循就近管理标准。

html PUBLIC -//W3C//DTD XHTML 1.0
Transitional//EN
html xmlns= head titleYanCms左侧…

达成步骤4:看重

为明白决这几个题材我们还索要去重新,对刚刚的多个helper改造一下即可。

JavaScript

//app.js hbs.registerHelper(‘css’, function(str, option) { var cssList =
this.cssList || []; if(cssList.indexOf(str)<0) { cssList.push(str);
} this.cssList = cssList.concat(); }); hbs.registerHelper(‘js’,
function(str, option) { var jsList = this.jsList || [];
if(jsList.indexOf(str)<0) { jsList.push(str); } this.jsList =
jsList.concat(); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//app.js
hbs.registerHelper(‘css’, function(str, option) {
  var cssList = this.cssList || [];
  if(cssList.indexOf(str)<0) {
    cssList.push(str);
  }
  this.cssList = cssList.concat();
});
hbs.registerHelper(‘js’, function(str, option) {
  var jsList = this.jsList || [];
  if(jsList.indexOf(str)<0) {
    jsList.push(str);
  }
  this.jsList = jsList.concat();
});

                    
                    </ul>
                </li>

Nodejs后端使用hbs

Node后端使用hbs也卓殊有利于,这里我用的是express框架,直接后端渲染。当然更精致的做法就是首屏渲染、仅移动端后端渲染了,在那种混搭的场合模板是可以通用的,那样就裁减了肯定的付出工作量。近年来express中自带4种模板引擎,jade、esj、hogan与hbs,我是使用express-generator来生成项目脚手架的,输入指令为:
express –hbs 项目名。

express-generator中的hbs用的是hbs库(

1 res.render('index', {
2   title: 'Express',
3   head: '<h1>head part</h1>',
4   layout: true  //默认为true,设为false则不启用layout模板
5 });

现阶段我所接触到的hbs项目都是express+hbs+zepto/jq这一套,如若有用别样前端框架的话,一般也不会用到hbs了,所以只说说那种气象。后端渲染跟前端渲染的开发方式略有差别,但思路依然一样的要做组件化开发。上文说过前端选取hbs的时候是以js为输入,而在后端使用hbs的话个人认为更符合选择一些模板的办法。

自我的目录是那般的:

亚洲必赢官网 2

页面统一放入views中,局地模板放入views/partial里面。js和css如故按照法定默许的方法集中管理。使用一些模板要先挂号,须求在app.js那些服务器脚本里面参与以下代码:

1 var hbs = require('hbs');
2 hbs.registerPartials(__dirname + '/views/partials');

模板文件中引入小模板:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4   <title>{{title}}</title>
 5   <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
 6   <link rel="stylesheet" href="/css/main.css"/>
 7   {{> resource}}
 8 </head>
 9 <body>
10 {{> header}}
11 <div class="container">
12   {{{body}}}
13 </div>
14 {{> footer}}
15 </body>
16 </html>

resource模板首要是决定差异页面引入的例外资源:

1 {{#each css}}
2   <link rel='stylesheet' href={{this}} />
3 {{/each}}
4 {{#each js}}
5   <script src={{this}}></script>
6 {{/each}}

页面渲染的时候就是这么的:

1 res.render('index', {
2   title: 'Express',
3   css: ['/css/home.css', '/css/home_add.css'],
4   js: ['/js/home.js'],
5   name: "茄果" //这个是页面中用到的数据,与title同一性质
6 });

那种方法的一个标题就是css、js那几个资源的写法跟大家平日直接在html引用的法子分裂。比如我想资源引用写在页面中,比如home.hbs里面,要是直白写入home.hbs里面的话,内容是直接插入到{{{body}}}的岗位,但我们想要的是在head的职责啊。那几个怎么贯彻啊?往日咱们定义partial只是为了简单的替换,这一遍除了替换还要做一个插入dom的操作,那一个将要选择helper来帮我们做到了。很多时候我们要把css放入底部,而把js放在页面底部,所以layout文件要改造成:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4   <title>{{title}}</title>
 5   <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
 6   <link rel="stylesheet" href="/css/main.css"/>
 7   {{#each cssList}}
 8     <link rel='stylesheet' href={{this}} />
 9   {{/each}}
10 </head>
11 <body>
12 {{> header}}
13 <div class="container">
14   {{{body}}}
15 </div>
16 {{> footer}}
17 {{#each jsList}}
18   <script src={{this}}></script>
19 {{/each}}
20 </body>
21 </html>

方今即使注册helper把hbs文件中定义的值传入cssList、jsList中即可。此外还要考虑到页面组件引用的时候也许会冒出重复依赖的动静,所以要做一个去重的劳作。注册helper与注册partial一样,都要写在app.js文件中,下边给出css的写法,js也类似:

 1 hbs.registerHelper('css', function(str, option) {
 2   var cssList = this.cssList || [];
 3   str = str.split(/[,,;;]/);
 4   console.log('css: ',str);
 5   str.forEach(function (item) {
 6     if(cssList.indexOf(item)<0) {
 7       cssList.push(item);
 8     }
 9   });
10   this.cssList = cssList.concat();
11 });

页面中引入css、js就相应是那样:

{{css "/css/home_add.css"}}
{{js "/js/home.js"}}
{{> p}}
<p>This is home page!</p>

地方例子中的局地模板p作为一个零部件,也引述了相应的css和js,写法跟页面的写法是千篇一律的。

心想事成步骤5:合并

终极一步优化。为了减小请求,可以将不一致组件所需的资源文件举办统一。那里推荐一个插件loader。

示范代码下载地址

如上就是关于后端利用模板完成组件化的探索,已毕上虽无难题,可是由于方今不曾新的类型,不能在实际项目中应用,所以不领会会不会推动别样的“坑”。欢迎有趣味的爱人使用后与自我交换~

打赏辅助我写出越来越多好小说,谢谢!

打赏小编

                <li>
                    <a class=”head”>权限管理</a>
                    <ul>
                        <li>
                            <a href=”#”
target=”rightFrame”>暂未开放</a>
                        </li>
                        <li>
                            <a href=”#”
target=”rightFrame”>暂未开放</a>
                        </li>

总结

handlebars作为一个格外轻量级的模板引擎,单纯从沙盘这么些效应上看,他的左右端通用性强,命令不难明了,代码可读性强。但她是一个单独的模板引擎,在前端框架满天飞的年代感觉是有点弱了。无论是前端照旧后端,种种大框架都有渲染模块。当然不欣赏大框架的全家桶倒是可以考虑采用handlebars,所以主要仍旧要看项目吧。青菜萝卜,各具有好。

 

文字较多,惯例上图吧。

亚洲必赢官网 3

打赏协助自己写出越来越多好作品,谢谢!

任选一种支付形式

亚洲必赢官网 4
亚洲必赢官网 5

1 赞 收藏
评论

                    
                    </ul>

关于笔者:亚里士朱建德

亚洲必赢官网 6

微信公众号“web学习社”;js全栈工程师,熟稔node.js、mongoDB。开发者头条top10专栏撰稿人慕课网签约助教个人博客:yalishizhude.github.io

个人主页 ·
我的小说 ·
19 ·
    

亚洲必赢官网 7

                </li>
            </ul>
        </div>

    </body>
</html>

复制代码 代码如下:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“;
<html xmlns=”;
<head>
    <title>YanCms左侧导航栏</title>
    <script src=”js/jquery-1.4.2.min.js”
type=”text/javascript”></script>
    <script src=”js/jquery-ui-1.8.custom.min.js”
type=”text/javascript”></script>
    <script type=”text/javascript”>
        $(document).ready(function () {
            //#title代表页面中点击的要素
            $(“.title”).click(function () {
                var con = $(this).html();
                //#getTitle代表页面中想要得到title的值元素
                $(“#getTitle”).html(con);
                //$(this).attr(‘href’)获取超链接
                var con1 = $(this).attr(‘href’);
               // $(“#getTitle”).attr(“href”, “con1”);
               // alert(con1);
            });
        });
   </script>
    <script type=”text/javascript”>
        jQuery().ready(function () {
            jQuery(“#navigation”).accordion({
                header: ‘.head’,
                event: ‘click’,
                fillSpace: true,
                animated: ‘bounceslide’
            });
        });
 </script>
    <link href=”css/left.css” rel=”stylesheet” type=”text/css”
/>
 </head>
<body style=”background-color:#e6f4fa;” >
        <div class=”subMenuTitle” id=”getTitle”><a
href=”#”>主作用菜单</a></div>
  <div style=”height:100%;”>
   <ul id=”navigation”>
    <li>
     <a class=”head”>种类管理</a>
     <ul>
      <li class=”title”>
       <a href=”#1233333″ >博文列表</a>
      </li>

      <li class=”title”>
       <a href=”#”>添加博文</a>
      </li>
     </ul>
    </li>
    <li>
     <a class=”head”>序列管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”> 连串列表</a>
      </li>
        </ul>
    </li>
    <li>
     <a class=”head”>友情链接</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”> 链接列表</a>
      </li>
      <li>
       <a href=”#” target=”rightFrame”>添加链接</a>
      </li>

     </ul>
    </li>
    <li>
     <a class=”head”>系统管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”>修改管理员密码</a>
      </li>

    
     </ul>
    </li>

    <li>
     <a class=”head”>权限管理</a>
     <ul>
      <li>
       <a href=”#” target=”rightFrame”>暂未开放</a>
      </li>
      <li>
       <a href=”#” target=”rightFrame”>暂未开放</a>
      </li>

    
     </ul>

    </li>
   </ul>
  </div>

 </body>
</html>

你或许感兴趣的稿子:

  • BootStrap学习笔记之nav导航栏和面包屑导航
  • Bootstrap
    CSS组件之面包屑导航(breadcrumb)
  • Bootstrap组件学习之导航、标签、面包屑导航(精品)
  • php完毕面包屑导航例子分享
  • php可应用于面包屑导航的迭代寻找家谱树完成形式
  • php可应用于面包屑导航的递归寻找家谱树完毕格局
  • thinkphp完成面包屑导航(当前地方)例子分享
  • 面包屑导航详解
网站地图xml地图