# 视图 &amp; 模板 <p class="uk-article-lead">控制器处理传入的请求时,视图负责渲染响应。为了实现这一点,它使用一个模板引擎。在Pagekit,您可以使用纯PHP模板或 twig 模板引擎。</p> [toc=2] ## 已渲染的视图响应 渲染视图最常见的方式是从控制器操作中返回一个数组。使用 `$view` 属性将参数传到你的视图渲染器。 ```php public function indexAction($name = '') { return [ '$view' => [ // 在网站的 <title> 中渲染 'title' => 'Hello World', //已渲染的视图文件 'name' => 'hello:views/index.php', ], // 传递参数到视图文件 'name' => $name ]; } ``` 已渲染的视图文件看起来是这样: ```php <!-- packages/pagekit/extension-hello/views/index.php --> <h1>Hello <?= $name ?></h1> <p> ... </p> ``` 这个视图默认包裹在主要布局(main layout)中。要避免此行为,你可以在 `$view` 数组中修改 `'layout' => false`。 ## 手动渲染视图 可以手动访问 `View` 服务来渲染模板文件。这会在动态判断加载哪些视图时派上用场。注意,在下面的例子中 `hello:` 指的是使用 [模块](224131)中的源码简写方法定义的简写。。 ```php use Pagekit\Application as App; class MyController { public function anotherViewAction() { return App::view()->render('hello:views/view.php', ['id' => 1]); } } ``` 相关视图文件: ```HTML <!-- packages/pagekit/extension-hello/views/index.php --> <h1>You are viewing article number <?= $id ?></h1> <p> ... </p> ``` ## Templating 这些视图是使用 PHP 模板引擎渲染的,模板引擎提供了已定义的全局模板变量和一系列视图助手。 ### 引入其他视图 使用 `$view`助手在视图中渲染子视图。 `render` 方法评估并返回模板文件的内容。这与在控制器中手动渲染视图是相同的。 ```php $view->render('hello:views/view.php', ['id' => 1]) ``` ### 链接到路由 正如前面看到的,每个路径都有一个名称,你可以动态生成链接到具体路线的链接。`Url`暴露了 `UrlProvider`的功能。 ```HTML <a href="<?= $view->url('@hello/default/view') ?>">View all articles</a> <a href="<?= $view->url('@hello/default/view', ['id' => 23]) ?>">View article 23</a> ``` 可以链接到资源,比如图片或其他文件,使用 URL 提供者(`UrlProvider`)的 `getStatic($path)` 方法。 ```HTML <img src="<?= $view->url()->getStatic('hello:extension.svg') ?>" alt="Extension icon" /> ``` ## 处理资源/Assets 资源是指项目中需要的静态文件,包括CSS、JS和图片文件等。 ### 生成静态资源的 URL 要生成静态资源的路由,使用`UrlProvider` 类的 `getStatic` 方法。 ```php <img src="<?= $view->url()->getStatic('my-assets/image.jpg') ?>"> ``` ### 在视图文件中引入 CSS 在视图文件中引入 CSS,调用 `View` 中的 `style` 助手。 ```php $view->style($id, $path [, $dependencies ]) ``` 第一个参数是样式表的唯一标识符。如果为多个样式表使用同一个标识符,Pagekit只会引入最后一个。第二个参数是样式表的路径,可以使用 `theme:` 作为 'theme'包根目录的参照。可以通过可选的第三个参数定义依赖。 Example: ``` <?php $view->style('theme', 'theme:css/theme.css') ?> <?php $view->style('theme', 'theme:css/theme.css', 'uikit') ?> <?php $view->style('theme', 'theme:css/theme.css', ['uikit', 'somethingelse']) ?> ``` **Note** 这并不会直接在 HTML 中输出,它会将 CSS 文件添加到 Pagekit 的资源管理器(Pagekit Asset Manager)。样式表会引入到主题的 `<head>` 部分。 ### 在视图文件中引入 JS 要在模板中引入 javascript 文件,调用 `#view` 对象的 `script` 助手,作用和 `style` 助手一样。 ```php $view->script($id, $path [, $dependencies ]) ``` 第一个参数是脚本资源的唯一标识符。如果为多个脚本使用了相同的标识符,Pagekit 只会引入最后一个。第二个参数是脚本的路径,可以使用 `theme:` 作为 'theme'包根目录的参考。可以通过可选的第三个参数定义依赖。 Example: ``` <?php $view->script('theme', 'theme:js/theme.js') ?> <?php $view->script('theme', 'theme:js/theme.js', 'jquery') ?> <?php $view->script('theme', 'theme:js/theme.js', ['jquery', 'uikit']) ?> ``` **Note** 在内部,`style()` 和 `script()` 各自使用它们自己的资源管理器。这些都是彼此分开的,可以无冲突地为 CSS 和 JS 文件指定相同的名称(前面的例子里都叫做 `theme`)。然而,两个脚本或样式表不能使用相同的名称。例如,在添加两个样式表时,一个可以称为 'theme',另一个称为 'custom'。 ### 异步和延迟脚本执行/Async and deferred script execution 默认地,脚本会在已渲染的 HTML 标签的 head 部分被引入,是即时获取并执行的。之后,浏览器才会继续解析页面。 要改变这样的行为,可以在加载脚本时使用关键字 `async` 和 `defer`。在 PHP 代码中设置适当的选项,于是在最后的 `<script>` 标签中将会有这些属性。 |属性 | 描述| |--------- | -----------| |`async` | 告诉浏览器异步执行脚本,这意味着就算是在执行脚本,页面解析也会继续。| |`defer` | 告诉浏览器在页面解析完毕后再执行脚本。浏览器对于这个 HTML 特性的支持并不完美,只是会在脚本执行的顺序很重要时使用它才会导致一些问题。| Example: 延迟执行,无依赖。 ``` <?php $view->script('theme', 'theme:js/theme.js', [], ['defer']) ?> ``` Example: 有依赖的延迟和异步执行。 ``` <?php $view->script('theme', 'theme:js/theme.js', ['jquery', 'uikit'], ['defer', 'async']) ?> ``` ## Twig 模板 可以在主题和扩展模板中使用 Twig 来替代原生的 PHP 模板。在 Twig 官方文档的基础[Twig 语法和特性](http://twig.sensiolabs.org/doc/templates.html) 上找到相关资料。类似于官方使用默认的PHP模板制作的的 Hello 主题,还有一个 [boilerplate Twig theme](https://github.com/florianletsch/theme-twig) ,可以用它作为起点。 ### 使用 Twig 构建主题 默认地,Pagekit 主题用到的主要模板文件,位于 `views/template.php`,并且它是使用默认的 PHP 渲染器进行渲染的。在主题的 `index.php` 中,你可以另外定义一个布局文件用作主要模板。 ``` /** * 使用 Twig 模板修改默认布局 */ 'layout' => 'views:template.twig', ``` 文件扩展名 `*.twig` 将导致 Pagekit 使用 Twig 引擎来渲染模板。主题的 `views/template.twig` 的简单例子,看起来是这样: ``` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> {{ view.render('head') | raw }} {{ view.style('theme', 'theme:css/theme.css') }} {{ view.script('theme', 'theme:js/theme.js') }} </head> <body> <!-- Render logo or title with site URL --> <a href="{{ view.url().get() }}"> {% set logo = params.logo %} {% if logo %} <img src="{{ logo }}" alt="Logo"> {% else %} {{ params.title }} {% endif %} </a> <!-- Render menu position --> {% if view.menu().exists('main') %} {{ view.menu('main') | raw }} {% endif %} <!-- Render widget position --> {% if view.position().exists('sidebar') %} {{ view.position('sidebar') | raw }} {% endif %} <!-- Render system messages --> {{ view.render('messages') | raw }} <!-- Render content --> {{ view.render('content') | raw }} <!-- Insert code before the closing body tag --> {{ view.render('footer') | raw }} </body> </html> ``` 如你所见,可以为输出的已转义内容使用基础的 Twig 语法(`{{ ... }}`),未转义内容使用 (`{{ ... | raw }}`)。默认的控制结构,比如 `if` 和 `for` 都是可用的,更多详情查阅[Twig 语法](http://twig.sensiolabs.org/doc/templates.html) 文档。 Pagekit 的视图助手和函数通过可以在模板中用作 `view` 的视图渲染器暴露。PHP 表达式可以轻松转换为 Twig 语法,例如为当前页面添加 CSS 文件: ```html <!-- PHP version --> <?php $view->style('theme', 'theme:css/theme.css'); ?> <!-- Twig version --> {{ view.style('theme', 'theme:css/theme.css') }} ```