视图系统

最后更新: 2026-01-27 11:02:47

视图系统

Unicode Framework 提供了灵活的视图系统,支持多种模板引擎,包括 Smarty 和 Vue3。

视图基础

渲染视图

使用 view() 辅助函数渲染视图:

use function view;

// 渲染视图 return view('user/profile', [ 'user' => $user, 'title' => '用户资料', ]);

// 使用指定引擎 return view('user/profile', ['user' => $user], 'vue');

在控制器中使用

namespace App\Index\Controller;

use Unicode\Framework\Http\Request; use Unicode\Framework\Http\Response;

class UserController { public function profile(Request $request): Response { $user = db('users')->where('id', 1)->first();

$html = view('user/profile', [ 'user' => $user, 'title' => '用户资料', ]);

return Response::html($html); } }

检查视图是否存在

use Unicode\Framework\View\View;

if (View::exists('user/profile')) { return view('user/profile', ['user' => $user]); }

Smarty 模板引擎

基本语法

Smarty 是框架默认的模板引擎,提供强大的模板功能。

#### 变量输出

{ 输出变量 }
{$user.name}
{$user.email}

{ 数组访问 } {$user.profile.bio}

{ 默认值 } {$user.name|default:'匿名用户'}

#### 条件判断

{if $user.status == 'active'}
    <p>用户已激活</p>
{else}
    <p>用户未激活</p>
{/if}

{ 多条件 } {if $user.age >= 18} <p>成年人</p> {elseif $user.age >= 13} <p>青少年</p> {else} <p>儿童</p> {/if}

#### 循环

{ foreach 循环 }
{foreach $users as $user}
    <div>
        <h3>{$user.name}</h3>
        <p>{$user.email}</p>
    </div>
{/foreach}

{ 带索引的循环 } {foreach $users as $index => $user} <div class="user-{$index}"> {$user.name} </div> {/foreach}

#### 包含模板

{ 包含其他模板 }
{include file='header.html'}

{ 传递变量 } {include file='user/card.html' user=$user}

{ 包含公共模板 } {include file='common/footer.html'}

#### 函数和修饰符

{ 字符串修饰符 }
{$user.name|upper}
{$user.name|lower}
{$user.name|capitalize}
{$user.name|truncate:20}

{ 日期格式化 } {$user.created_at|date_format:'%Y-%m-%d'}

{ HTML 转义 } {$user.bio|escape:'html'}

{ 默认值 } {$user.avatar|default:'/images/default-avatar.png'}

Smarty 配置

config/view.php 中配置:

return [
    'default_engine' => 'smarty',
    'engines' => [
        'smarty' => [
            'template_extension' => '.html',
            'compile_dir' => 'runtime/view/smarty/compile',
            'cache_dir' => 'runtime/view/smarty/cache',
            'caching' => false,
            'cache_lifetime' => 3600,
            'debugging' => false,
            'escape_html' => true,
        ],
    ],
];

模板目录结构

app/index/view/
├── user/
│   ├── profile.html
│   └── list.html
├── common/
│   ├── header.html
│   └── footer.html
└── index.html

Vue3 模板引擎

基本语法

Vue3 模板引擎支持 Vue3 的模板语法。

#### 插值表达式

<template>
  <div>
    <h1>{{ user.name }}</h1>
    <p>{{ user.email }}</p>
  </div>
</template>

#### 指令

<template>
  { v-if 条件渲染 }
  <div v-if="user.status === 'active'">用户已激活</div>
  <div v-else>用户未激活</div>

{ v-for 列表渲染 } <ul> <li v-for="user in users" :key="user.id"> {{ user.name }} </li> </ul>

{ v-bind 属性绑定 } <img :src="user.avatar" :alt="user.name" />

{ v-model 双向绑定(表单) } <input v-model="user.name" type="text" />

{ v-show 显示/隐藏 } <div v-show="user.isVisible">可见内容</div>

{ v-html 原始 HTML } <div v-html="user.bio"></div> </template>

#### 事件处理

<template>
  <button @click="handleClick">点击</button>
  <button @click="handleSubmit($event)">提交</button>
</template>

Vue3 SSR

框架支持 Vue3 服务端渲染(SSR)。

#### 启用 SSR

config/view.php 中配置:

return [
    'engines' => [
        'vue' => [
            'vue3_ssr' => [
                'enabled' => true,
                'node_path' => '/usr/bin/node',
                'script_path' => 'runtime/vue3-ssr/render.js',
            ],
        ],
    ],
];

#### 使用 SSR

use function vue_spa;

// 渲染 Vue3 SPA 入口页面 return vue_spa( initialData: ['user' => $user], appId: 'app', entryFile: 'js/main.js', options: [ 'title' => '我的应用', 'meta' => [ 'description' => '应用描述', ], ] );

Vue3 SPA 支持

框架提供了 vue_spa() 辅助函数来渲染 Vue3 单页应用入口:

use function vue_spa;

return vue_spa([ 'user' => $user, 'config' => [ 'apiUrl' => '/api', ], ], 'app', 'js/main.js');

视图配置

全局配置

config/view.php:
return [
    // 默认模板引擎
    'default_engine' => 'smarty',

// 视图文件目录(null 表示使用默认路径) 'path' => null,

// 模板引擎配置 'engines' => [ 'smarty' => [ 'template_extension' => '.html', 'compile_dir' => 'runtime/view/smarty/compile', 'cache_dir' => 'runtime/view/smarty/cache', 'caching' => false, 'escape_html' => true, ], 'vue' => [ 'vue3_ssr' => [ 'enabled' => false, ], ], ], ];

应用级配置

在多应用模式下,可以在 app/{app-name}/config/view.php 中配置应用特定的视图设置:

// app/index/config/view.php
return [
    'default_engine' => 'vue',
    'engines' => [
        'smarty' => [
            'template_dir' => 'app/index/view',
        ],
    ],
];

视图路径

框架会自动检测视图路径:

  • 多应用模式app/{app-name}/view/
  • 单应用模式app/{default-app}/view/
  • 自定义路径:在配置中指定 path
  • 视图辅助函数

    view()

    use function view;
    

    // 基本用法 $html = view('template', ['data' => $data]);

    // 指定引擎 $html = view('template', ['data' => $data], 'vue');

    vue_spa()

    use function vue_spa;
    

    // 渲染 Vue3 SPA 入口 $html = vue_spa( initialData: ['user' => $user], appId: 'app', entryFile: 'js/main.js', options: [ 'title' => '页面标题', 'meta' => [ 'description' => '页面描述', ], ] );

    最佳实践

    1. 模板组织

    app/index/view/
    ├── layouts/          # 布局模板
    │   ├── main.html
    │   └── admin.html
    ├── components/       # 组件模板
    │   ├── header.html
    │   └── footer.html
    ├── user/            # 用户相关模板
    │   ├── profile.html
    │   └── list.html
    └── index.html        # 首页模板
    

    2. 使用布局

    { layouts/main.html }
    <!DOCTYPE html>
    <html>
    <head>
        <title>{$title|default:'我的网站'}</title>
    </head>
    <body>
        {include file='components/header.html'}
    

    <main> {block name='content'}{/block} </main>

    {include file='components/footer.html'} </body> </html>

    { user/profile.html } {extends file='layouts/main.html'}

    {block name='content'} <h1>用户资料</h1> <p>{$user.name}</p> {/block}

    3. 数据转义

    { 自动转义 HTML(推荐) }
    {$user.bio|escape:'html'}
    

    { 需要输出 HTML 时 } {$user.bio|unescape}

    4. 缓存优化

    // 在配置中启用缓存(生产环境)
    'engines' => [
        'smarty' => [
            'caching' => true,
            'cache_lifetime' => 3600,
        ],
    ],
    

    5. 模板继承

    { base.html }
    <!DOCTYPE html>
    <html>
    <head>
        <title>{block name='title'}默认标题{/block}</title>
    </head>
    <body>
        {block name='content'}{/block}
    </body>
    </html>
    

    { page.html } {extends file='base.html'}

    {block name='title'}页面标题{/block}

    {block name='content'} <h1>页面内容</h1> {/block}

    常见问题

    Q: 如何切换模板引擎?

    A: 在配置中设置 default_engine,或在调用 view() 时指定引擎。

    Q: 视图文件应该放在哪里?

    A: 默认在 app/{app-name}/view/ 目录下,可以在配置中自定义。

    Q: 如何传递数据给视图?

    A: 使用 view() 函数的第二个参数传递数据数组。

    Q: 支持哪些模板引擎?

    A: 目前支持 Smarty 和 Vue3,可以通过接口扩展其他引擎。

    Q: 如何启用视图缓存?

    A: 在配置中设置 caching => truecache_lifetime

    相关文档

  • Vue3 集成 - Vue3 SSR 和 SPA 详细说明
  • 多应用架构 - 多应用模式下的视图
  • 路由系统 - 路由和视图结合使用