一、什么是模板继承
模板继承不同于模板布局,甚至来说,应该在模板布局的上层。模板继承其实并不难理解,就好比类的继承一样,模板也可以定义一个基础模板(或者是布局),并且其中定义相关的区块(block),然后继承(extend)该基础模板的子模板中就可以对基础模板中定义的区块进行重载。
或者更确切的比喻,模板继承更像是java中的implement,而不是extent,尽管在大量php、python、ruby框架中称之为:template extend。
因此,模板继承的优势其实是设计基础模板中的区块(block)和子模板中替换这些区块。每个区块由标签组成(thinkphp为例),并且不支持block标签的嵌套。
模板继承,已广泛使用于诸如php、python、ruby等web框架中,但早先的模板如jst、ftl等并不原生支持模板继承。
二、为什么要考虑模板继承
首先对比一下几乎所有渲染模板都有的,模板布局。用流行性语言描绘,模板布局的思想,是一种不带交互的组件化思想。
模板布局应用最为广泛,譬如php中的require、freemarker中的macro - 、django中的{% include };用前端的模板加以对比,则如jst、regular中的。其核心思想即将大部分页面的公共部分进行拆分,通过在不同页面中组装,达到模板复用的目的。
例如:
这种模板布局的思想,可以解决大多数的问题,但是如果有大量同类页面,但每个页面又有些许差异时,这种模板组件的组装就逐渐体现成一种体力活。
首先各个组件是耦合在最终生成的模板页面中的,譬如以下的代码逻辑:
内容 。。。。。。
那么每修改内容部分就需要格外小心,不要误动了include组件。当然也可以把内容部分抽离出来单独封装成模板组件,组合载入。
另一个可以体现大量复用思想的场景(仅举例而已):业务有多个子应用,每个应用的首页基本结构相近,但是又各有差异。另外每个应用会有不同变化位置的广告位
那么使用常规思路就是分别为应用设计A、B、C三个页面(每个相互独立,引入组件),每个页面分别要include各自所需的组件(如图1号页面、2号页面等),当有广告活动时,需要再在A、B、C三个页面中添加对应的广告(可能是在页面中加入广告锚点),然后定义广告组件include进去。等到活动结束再把对应的广告锚点撤销。
那么再来对比使用模板继承的情形:
首先需要定义基类模板,诸如base.html
A、B、C三个页面继承于base.html,只需要重新定义A、B、C的差异部分
如A模板(只需引入差异部分,无需引入1号页面、3号页面等):
{% extend base.html %}
{% block %}
A页面逻辑
{% block %}
{% include 2号页面组件 %}
同时A、B、C的带广告页面又继承于A、B、C,如A的活动模板:
{% extend A.html %}
{% block %}
{% include广告1 %}
{% block %}
将广告逻辑与A页面逻辑剥离开,且切换方便,代码复用性强。对比于原来可能需要在A页面基础上添加广告位置(撤掉又需要在A页面上删除)或者拷贝A页面在改写(大量的代码冗余),相当便利。
模板继承的思想并不是抛弃原有的模板组件的使用,而是在其上做了加强,对于有大量同构页面,将模板继承和模板组合的思想灵活应用,必定事半功倍。
三、Thinkphp、django(python)中的模板继承
1.Thinkphp中的模板继承
例如基模板:
1.
2.
3.
4.标题
5.
6.
7.菜单
8.左边分栏
9.主内容
10.右边分栏
11.底部
12.
13.
对应继承模板:
1.
2.{$title}
3.
4.首页
5.资讯
6.论坛
7.
8.
9.
10.
11.{$vo.title}
12.{$vo.content}
13.
14.
15.
16.最新资讯:
17.
18.{$new.title}
19.
20.
21.
22.@ThinkPHP2012版权所有
23.
2.Django中的模板继承使用
{%extends"base.html"%}
{%blocktitle%}Articles for{{year}}{%endblock%}
{%blockcontent%}
Articles for{{year}}
{%forarticleinarticle_list%}
{{article.headline}}
By{{article.reporter.full_name}}
Published{{article.pub_date|date:"F j, Y"}}
{%endfor%}
{%endblock%}
四、Freemarker实现模板继承
Freemarker并不原生支持模板继承,但他具有完善的模板组件,称之为宏(macro)。而我们可以基于宏来实现模板继承。
首先,我们探究一下什么是继承的核心?
我理解的继承就是子类拥有父类所以的方法、特性,同时子类又可以重写父类的这些特性与方法,并拥有自己独特的方法。
那么如果freemark的“基模板”本身就是一个宏,且可以同时内嵌组件化的宏呢?
诸如:
#macro>
那么子类继承父类只需要重写其所不同的部分,如
#macro>
那么即实现了对base的继承,同时定义了子模板自己的差异。其他不原生支持模板继承思想的模板体系,也可以参考。
注意:模板继承的思想并不是抛弃原有的模板组件的使用,而是在其上做了加强,对于有大量同构页面,将模板继承和模板组合的思想灵活应用,必定事半功倍!
参考示例:
django模板继承:http://python.usyiyi.cn/django/intro/overview.html#design-your-templates
thinkphp模板继承:http://www.thinkphp.cn/info/178.html
本文来自网易实践者社区,经作者陈盛授权发布。