php 原生 实现模板继承,谈谈模板继承思想的实现(以freemarker为例)

一、什么是模板继承

模板继承不同于模板布局,甚至来说,应该在模板布局的上层。模板继承其实并不难理解,就好比类的继承一样,模板也可以定义一个基础模板(或者是布局),并且其中定义相关的区块(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中的。其核心思想即将大部分页面的公共部分进行拆分,通过在不同页面中组装,达到模板复用的目的。

例如:

6f4661a62c3daa1aa4f9984606509694.png

这种模板布局的思想,可以解决大多数的问题,但是如果有大量同类页面,但每个页面又有些许差异时,这种模板组件的组装就逐渐体现成一种体力活。

首先各个组件是耦合在最终生成的模板页面中的,譬如以下的代码逻辑:

内容 。。。。。。

内容 。。。。。。

那么每修改内容部分就需要格外小心,不要误动了include组件。当然也可以把内容部分抽离出来单独封装成模板组件,组合载入。

另一个可以体现大量复用思想的场景(仅举例而已):业务有多个子应用,每个应用的首页基本结构相近,但是又各有差异。另外每个应用会有不同变化位置的广告位

70e0d49b2bdee8d967bfaa07743febb6.png

那么使用常规思路就是分别为应用设计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

本文来自网易实践者社区,经作者陈盛授权发布。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Freemarker 模板中,可以使用内置函数 `.time` 来打印时间戳。 具体使用方法是在模板中使用 `${.time}` 这样的表达式,Freemarker 将会把当前时间戳以毫秒为单位打印出来。 例如,下面是一个简单的模板,用于打印当前时间戳: ``` <p>当前时间戳:${.time}</p> ``` 如果你想把时间戳以其他格式打印出来,可以使用 Freemarker 的时间格式函数。例如,要把时间戳以 yyyy-MM-dd HH:mm:ss 的格式打印出来,可以使用如下表达式: ``` <p>当前时间:${.time?string("yyyy-MM-dd HH:mm:ss")}</p> ``` 请注意,Freemarker 使用的是 UTC 时间,因此打印出来的时间可能与你本地的时间不同。如果你需要打印本地时间,可以使用 `.now` 函数来代替 `.time` 函数。 例如,要把本地时间以 yyyy-MM-dd HH:mm:ss 的格式打印出来,可以使用如下表达式: ``` <p>当前时间:${.now?string("yyyy-MM-dd HH:mm:ss")}</p> ``` 希望这些信息能帮到你! ### 回答2: 在 Freemarker 模板中,我们可以通过使用内置的日期和时间函数来打印时间戳。 要打印当前时间戳,可以使用如下的指令: ``` ${.now?long} ``` 该指令中,`now` 是一个内置的日期/时间对象,而 `?long` 表示将其转换为长整型即 Unix 时间戳。 如果你有一个具体的时间对象,你可以通过使用 `?long` 进行转换后再打印时间戳,例如: ``` ${myDate?long} ``` 其中 `myDate` 是一个 Date 对象。 需要注意的是,Freemarker 默认使用服务器的时区进行日期和时间的计算和显示,如果需要使用其他时区,可以使用内置的 `tz` 函数进行转换,例如: ``` ${.now?long} ``` 以上的指令将会使用服务器的时区进行日期转换,如果需要使用特定时区,可以进行如下修改: ``` ${.now?long} ``` 其中 `myTimeZone` 是一个已定义的时区,如 "GMT+8"。 通过上述方法,我们可以在 Freemarker 模板中轻松实现打印时间戳的功能。 ### 回答3: 在Freemarker模板中,我们可以使用内置的Date类型来处理时间戳,实现打印时间戳的功能。 首先,我们需要将时间戳转换为Date对象。可以使用`eval`内建指令来执行此操作。例如,假设我们有一个名为`timestamp`的变量存储时间戳,我们可以使用下面的语法将其转换为Date对象: ``` <#assign date = (timestamp * 1000)?eval?datetime> ``` 上述代码将`timestamp`乘以1000,以将其从秒转换为毫秒的时间戳,并通过`?eval?datetime`将其转换为Date对象,然后将其赋值给`date`变量。 接下来,我们就可以使用Freemarker的日期格式化指令来打印时间戳了。例如,我们可以使用`?string`内置函数将Date对象按照想要的格式转换为字符串,然后将其输出到模板上。以下是一个示例: ``` 时间戳:${timestamp} 转换后的日期:${date?string("yyyy-MM-dd HH:mm:ss")} ``` 上述代码将会在模板上输出时间戳和经过格式化后的日期。 总结起来,要在Freemarker模板中打印时间戳,我们需要先将时间戳转换为Date对象,然后使用日期格式化指令将其按照想要的格式输出到模板上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值