twig 模板设计 快速入门手册 中文
写了好几篇关于twig的东西。。居然还没写个快速入门之类的。现在就写
来源 http://twig.sensiolabs.org/doc/templates.html
概要
twig 的模板就是普通的文本文件,也不需要特别的扩展名,.html .htm .twig 都可以。
模板内的 变量 和 表达式 会在运行的时候被解析替换,标签(tags)会来控制模板的逻辑
下面是个最小型的模板,用来说明一些基础的东西
- <!DOCTYPE html>
- <html>
- <head>
- <title>My Webpage</title>
- </head>
- <body>
- <ulid="navigation">
- {% for item in navigation %}
- <li><ahref="{{ item.href }}">{{ item.caption }}</a></li>
- {% endfor %}
- </ul>
- <h1>My Webpage</h1>
- {{ a_variable }}
- </body>
- </html>
<!DOCTYPE html> <html> <head> <title>My Webpage</title> </head> <body> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}">{{ item.caption }}</a></li> {% endfor %} </ul> <h1>My Webpage</h1> {{ a_variable }} </body> </html>里面包含两种符号 {% ... %} 和 {{ ... }} 第一种用来控制的比如for循环什么的,第二个是用来输出变量和表达式的
ide 支持
很多ide 都对twig进行高亮支持。大伙自己找需要的吧。
- Textmate via the Twig bundle
- Vim via the Jinja syntax plugin
- Netbeans via the Twig syntax plugin
- PhpStorm (native as of 2.1)
- Eclipse via the Twig plugin
- Sublime Text via the Twig bundle
- GtkSourceView via the Twig language definition (used by gedit and other projects)
- Coda and SubEthaEdit via the Twig syntax mode
变量
程序会传递给模板若干变量,你需要在模板里输出他们。例如输出 $hello
- {{ hello }}
{{ hello }}如果传递给模板的是对象或者数组,你可以使用点 . 来输出对象的属性或者方法,或者数组的成员。或者你可以使用下标的方式。
- {{ foo.bar }}
- {{ foo['bar'] }}
{{ foo.bar }} {{ foo['bar'] }}如果你访问的值不存在就会返回null。TWIG有一整套的流程来确认值是否存在。
for.bar会进行以下操作
。。。如果 foo是个数组,就尝试返回bar成员,如果不存在的话,往下继续
。。。如果foo是个对象,会尝试返回bar属性,如果不存在的话,往下继续
。。。会尝试运行bar方法,如果不存在的话,往下继续
。。。会尝试运行getBar方法,如果不存在的话,往下继续
。。。会尝试运行isBar方法,如果不存在的话,返回null
for['bar'] 就简单很多了 for必须是个数组,尝试返回bar成员,如果不就返回null
全局变量
TWIG定义了有一些全局变量
- _self 这个参看macro标签
- _context 这个就是当前的环境
- _charset: 当前的字符编码
变量赋值
具体参见set标签
- {% set foo = 'foo' %}
- {% set foo = [1, 2] %}
- {% set foo = {'foo': 'bar'} %}
{% set foo = 'foo' %} {% set foo = [1, 2] %} {% set foo = {'foo': 'bar'} %}
过滤器 Firters
变量可以被过滤器修饰。过滤器和变量用(|)分割开。过滤器也是可以有参数的。过滤器也可以被多重使用。
下面这例子就使用了两个过滤器。
- {{ name|striptags|title }}
{{ name|striptags|title }}striptas表示去除html标签,title表示每个单词的首字母大写。更多过滤器参见我博客
过滤器也可以用在代码块中,参见 filter标签
- {% filter upper %}
- This text becomes uppercase
- {% endfilter %}
{% filter upper %} This text becomes uppercase {% endfilter %}
函数 Function
这个没什么好说的,会写程序的都知道,TWIG内置了一些函数,参考我的博客
举个例子 返回一个0到3的数组,就使用 range函数
- {% for i in range(0, 3) %}
- {{ i }},
- {% endfor %}
{% for i in range(0, 3) %} {{ i }}, {% endfor %}
流程控制
支持for循环 和 if/elseif/else结构。直接看例子吧,没什么好说的。
- <h1>Members</h1>
- <ul>
- {% for user in users %}
- <li>{{ user.username|e }}</li>
- {% endfor %}
- </ul>
<h1>Members</h1> <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul>
- {% if users|length > 0 %}
- <ul>
- {% for user in users %}
- <li>{{ user.username|e }}</li>
- {% endfor %}
- </ul>
- {% endif %}
{% if users|length > 0 %} <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul> {% endif %}
注释
{# ... #} 包围的内容会被注释掉,可以是单行 也可以是多行。载入其他模板
详见include标签(我博客内已经翻译好哦),会返回经过渲染的内容到当前的模板里
- {% include 'sidebar.html' %}
{% include 'sidebar.html' %}当前模板的变量也会传递到 被include的模板里,在那里面可以直接访问你这个模板的变量。
比如
- {% for box in boxes %}
- {% include "render_box.html" %}
- {% endfor %}
{% for box in boxes %} {% include "render_box.html" %} {% endfor %}在 render_box.html 是可以访问 box变量的 加入其他参数可以使被载入的模板只访问部分变量,或者完全访问不到。参考手册
我们先定义一个基本骨骼页base.html 他包含许多block块,这些都可以被子模板覆盖。
- <!DOCTYPE html>
- <html>
- <head>
- {% block head %}
- <linkrel="stylesheet"href="style.css"/>
- <title>{% block title %}{% endblock %} - My Webpage</title>
- {% endblock %}
- </head>
- <body>
- <divid="content">{% block content %}{% endblock %}</div>
- <divid="footer">
- {% block footer %}
- © Copyright 2011 by <ahref="http://domain.invalid/">you</a>.
- {% endblock %}
- </div>
- </body>
- </html>
<!DOCTYPE html> <html> <head> {% block head %} <link rel="stylesheet" href="style.css" /> <title>{% block title %}{% endblock %} - My Webpage</title> {% endblock %} </head> <body> <div id="content">{% block content %}{% endblock %}</div> <div id="footer"> {% block footer %} © Copyright 2011 by <a href="http://domain.invalid/">you</a>. {% endblock %} </div> </body> </html>我们定义了4个block块,分别是 block head, block title, block content, block footer
注意
1、block是可以嵌套的。
2、block可以设置默认值(中间包围的内容),如果子模板里没有覆盖,那就直接显示默认值。比如block footer ,大部分页面你不需要修改(省力),但你需要到时候仍可以方便到修改(灵活)
下面我看下 子模板应该怎么定义。
- {% extends "base.html" %}
- {% block title %}Index{% endblock %}
- {% block head %}
- {{ parent() }}
- <styletype="text/css">
- .important { color: #336699; }
- </style>
- {% endblock %}
- {% block content %}
- <h1>Index</h1>
- <pclass="important">
- Welcome on my awesome homepage.
- </p>
- {% endblock %}
{% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ parent() }} <style type="text/css"> .important { color: #336699; } </style> {% endblock %} {% block content %} <h1>Index</h1> <p class="important"> Welcome on my awesome homepage. </p> {% endblock %}注意 {% extends "base.html" %} 必须是第一个标签。其中 block footer就没有定义,所以显示父模板中设置的默认值
如果你需要增加一个block的内容,而不是全覆盖,你可以使用 parent函数
- {% block sidebar %}
- <h3>Table Of Contents</h3>
- ...
- {{ parent() }}
- {% endblock %}
{% block sidebar %} <h3>Table Of Contents</h3> ... {{ parent() }} {% endblock %}extends标签只能有一个,所以你只能有一个父模板,但有种变通到方法来达到重用多个模板到目的,具体参见手册的use标签
HTML转义
主要是帮助转义 尖括号等 <, >, &, " 可以有两种办法。一种是用标签,另一种是使用过滤器。其实TWIG内部就是调用 php 的htmlspecialchars 函数
- {{ user.username|e }}
- {{ user.username|e('js') }}
- {% autoescape true %}
- Everything will be automatically escaped in this block
- {% endautoescape %}
{{ user.username|e }} {{ user.username|e('js') }} {% autoescape true %} Everything will be automatically escaped in this block {% endautoescape %}因为{{是TWIG的操作符,如果你需要输出两个花括号,最简单到办法就是
- {{ '{{' }}
{{ '{{' }}还可以使用 raw 标签和raw 过滤器,详细参考手册
- {% raw %}
- <ul>
- {% for item in seq %}
- <li>{{ item }}</li>
- {% endfor %}
- </ul>
- {% endraw %}
{% raw %} <ul> {% for item in seq %} <li>{{ item }}</li> {% endfor %} </ul> {% endraw %}
macros宏
宏有点类似于函数,常用于输出一些html标签。
这里有个简单示例,定义了一个输出input标签的宏。
- {% macro input(name, value, type, size) %}
- <inputtype="{{ type|default('text') }}"name="{{ name }}"value="{{ value|e }}"size="{{ size|default(20) }}"/>
- {% endmacro %}
{% macro input(name, value, type, size) %} <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> {% endmacro %}宏参数是没有默认值的,但你可以通过default过滤器来实现。
一般来说宏会定义在其他到页面,然后通过import标签来导入,
- {% import "forms.html" as forms %}
- <p>{{ forms.input('username') }}</p>
{% import "forms.html" as forms %} <p>{{ forms.input('username') }}</p>你也可以只导入一个文件中部分宏,你还可以再重命名。
- {% from 'forms.html' import input as input_field, textarea %}
- <dl>
- <dt>Username</dt>
- <dd>{{ input_field('username') }}</dd>
- <dt>Password</dt>
- <dd>{{ input_field('password', type='password') }}</dd>
- </dl>
- <p>{{ textarea('comment') }}</p>
{% from 'forms.html' import input as input_field, textarea %} <dl> <dt>Username</dt> <dd>{{ input_field('username') }}</dd> <dt>Password</dt> <dd>{{ input_field('password', type='password') }}</dd> </dl> <p>{{ textarea('comment') }}</p>上面的代码表示 从forms.html中导入了 input 和 textarea宏,并给input重命名为input_field。
表达式
TWIG允许你在任何地方使用表达式,他的规则和PHP几乎一模一样,就算你不会PHP 仍然会觉得很简单。
最简单的有
字符串:“hello world” 或者 'hello world'
数字:42 或者 42.33
数组:['a','b','c']
哈希:{'a':'av', 'b':'bv'} 其中keys 可以不要引号 也可以是数字 还可以是一个表达式,比如{a:'av', b:'bv'} {1:'1v', 2:'2v'} {1+2:'12v'}
逻辑: true 或者 false
最后还有null
你可以嵌套定义
- {% set foo = [1, {"foo": "bar"}] %}
{% set foo = [1, {"foo": "bar"}] %}运算符
包括数字运算+ - * / %(求余数) //(整除) **(乘方)
- <p>{{ 2 * 3 }}=6
- <p>{{ 2 * 3 }}=8
<p>{{ 2 * 3 }}=6 <p>{{ 2 * 3 }}=8逻辑运算 and or not
比较运算 > < >= <= == !=
包含运算 in 以下的代码会返回 true
- {{ 1 in [1, 2, 3] }}
- {{ 'cd' in 'abcde' }}
{{ 1 in [1, 2, 3] }} {{ 'cd' in 'abcde' }}测试运算 is 这个不用多说 直接看代码
- {{ name is odd }}
- {% if loop.index is divisibleby(3) %}
- {% if loop.index is not divisibleby(3) %}
- {# is equivalent to #}
- {% if not (loop.index is divisibleby(3)) %}
{{ name is odd }} {% if loop.index is divisibleby(3) %} {% if loop.index is not divisibleby(3) %} {# is equivalent to #} {% if not (loop.index is divisibleby(3)) %}其他操作符
.. 建立一个指定开始到结束的数组,他是range函数的缩写,具体参看手册
- <PREclass=htmlname="code">{% for i in 0..3 %}
- {{ i }},
- {% endfor %}</PRE>
- <PRE></PRE>
- {% for i in 0..3 %}
- {{ i }},
- {% endfor %}
{% for i in 0..3 %} {{ i }}, {% endfor %}
| 使用一个过滤器
- {# output will be HELLO #}
- {{ "hello"|upper }}
{# output will be HELLO #} {{ "hello"|upper }}~ 强制字符串连接
- {{ "Hello " ~ name ~ "!" }}
{{ "Hello " ~ name ~ "!" }}?: 三元操作符
- {{ foo ? 'yes' : 'no' }}
{{ foo ? 'yes' : 'no' }}. [] 得到一个对象的属性,比如以下是相等的。
- {{ foo.bar }}
- {{ foo['bar'] }}
{{ foo.bar }} {{ foo['bar'] }}你还可以在一个字符串内部插入一个表达式,通常这个表达式是变量。 格式是 #{表达式}
- {{ "foo #{bar} baz" }}
- {{ "foo #{1 + 2} baz" }}
{{ "foo #{bar} baz" }} {{ "foo #{1 + 2} baz" }}
空白控制
和 php一样,在TWIG模板标签之后的第一个换行符会被自动删掉,其余的空白(包括 空格 tab 换行等)都会被原样输出。使用spaceless标签就可以删除这些HTML标签之间的空白
- {% spaceless %}
- <div>
- <strong>foo</strong>
- </div>
- {% endspaceless %}
- {# output will be <div><strong>foo</strong></div> #}
{% spaceless %} <div> <strong>foo</strong> </div> {% endspaceless %} {# output will be <div><strong>foo</strong></div> #}使用-操作符,可以很方便的删除TWIG标签之前或之后与html标签之间的空白。
- {% set value = 'no spaces' %}
- {#- No leading/trailing whitespace -#}
- {%- if true -%}
- {{- value -}}
- {%- endif -%}
- {# output 'no spaces' #}
{% set value = 'no spaces' %} {#- No leading/trailing whitespace -#} {%- if true -%} {{- value -}} {%- endif -%} {# output 'no spaces' #}
- {% set value = 'no spaces' %}
- <li> {{- value }} </li>
- {# outputs '<li>no spaces </li>' #}
{% set value = 'no spaces' %} <li> {{- value }} </li> {# outputs '<li>no spaces </li>' #}