
# 视图

- [简介](#introduction)
    - [使用 React / Svelte / Vue 编写视图](#writing-views-in-react-svelte-or-vue)
- [创建和渲染视图](#creating-and-rendering-views)
    - [嵌套视图目录](#nested-view-directories)
    - [创建第一个可用视图](#creating-the-first-available-view)
    - [判断视图是否存在](#determining-if-a-view-exists)
- [向视图传递数据](#passing-data-to-views)
    - [与所有视图共享数据](#sharing-data-with-all-views)
- [视图组合器](#view-composers)
    - [视图创建器](#view-creators)
- [优化视图](#optimizing-views)

## 简介

当然，直接从路由和控制器中返回完整的 HTML 文档字符串并不实用。幸运的是，视图提供了一种方便的方式，可以将所有 HTML 放置在单独的文件中。

视图将控制器 / 应用程序逻辑与展示逻辑分离，并存储在 `resources/views` 目录中。在使用 Laravel 时，视图模板通常使用 [Blade 模板语言](/docs/laravel/13.x/blade) 编写。一个简单的视图可能如下所示：

```blade
<!-- View stored in resources/views/greeting.blade.php -->

<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>
```

由于此视图存储在 `resources/views/greeting.blade.php` 中，因此我们可以使用全局 `view` 辅助函数返回它：

```php
Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});
```

> [!注意]
> 想了解更多关于如何编写 Blade 模板的信息？请查看完整的 [Blade 文档](/docs/laravel/13.x/blade) 以开始学习。

### 使用 React / Svelte / Vue 编写视图

许多开发者不再通过 Blade 使用 PHP 编写前端模板，而是开始更倾向于使用 React、Svelte 或 Vue 来编写模板。Laravel 借助 [Inertia](https://inertiajs.com/) 使这一过程变得简单。Inertia 是一个库，它可以让你的 React / Svelte / Vue 前端轻松连接到 Laravel 后端，而无需构建 SPA 时通常需要处理的复杂问题。



我们的 [React、Svelte 和 Vue 应用程序启动套件](/docs/laravel/13.x/starter-kits) 为您下一个基于 Inertia 的 Laravel 应用程序提供了一个很好的起点。

## 创建和渲染视图

您可以通过在应用程序的 `resources/views` 目录中放置一个 `.blade.php` 扩展名的文件来创建视图，或者使用 `make:view` Artisan 命令：

```shell
php artisan make:view greeting
```

`.blade.php` 扩展名会告知框架该文件包含一个 [Blade 模板](/docs/laravel/13.x/blade)。Blade 模板包含 HTML 以及 Blade 指令，这些指令允许您轻松输出变量值、创建 "if" 语句、遍历数据等等。

创建视图后，您可以使用全局 `view` 辅助函数从应用程序的路由或控制器中返回该视图：

```php
Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});
```

也可以使用 `View` 门面返回视图：

```php
use Illuminate\Support\Facades\View;

return View::make('greeting', ['name' => 'James']);
```

正如您所看到的，传递给 `view` 辅助函数的第一个参数对应于 `resources/views` 目录中的视图文件名称。第二个参数是一个应提供给视图使用的数据数组。在这个例子中，我们传递了 `name` 变量，该变量会通过 [Blade 语法](/docs/laravel/13.x/blade) 在视图中显示。

### 嵌套视图目录

视图也可以嵌套在 `resources/views` 目录的子目录中。可以使用 "点" 符号来引用嵌套视图。例如，如果您的视图存储在 `resources/views/admin/profile.blade.php`，您可以像下面这样从应用程序的路由 / 控制器中返回它：

```php
return view('admin.profile', $data);
```

> [!警告]
> 视图目录名称不应包含 `.` 字符。



### 创建第一个可用的视图

使用 `View` 门面的 `first` 方法，您可以从给定的视图数组中创建第一个存在的视图。如果您的应用程序或扩展包允许自定义或覆盖视图，这可能会非常有用：

```php
use Illuminate\Support\Facades\View;

return View::first(['custom.admin', 'admin'], $data);
```

### 判断视图是否存在

如果您需要判断某个视图是否存在，可以使用 `View` 门面。`exists` 方法会在视图存在时返回 `true`：

```php
use Illuminate\Support\Facades\View;

if (View::exists('admin.profile')) {
    // ...
}
```

## 向视图传递数据

正如您在前面的示例中看到的，您可以向视图传递一个数据数组，使这些数据可以在视图中使用：

```php
return view('greetings', ['name' => 'Victoria']);
```

以这种方式传递信息时，数据应该是一个包含键 / 值对的数组。向视图提供数据后，您可以在视图中通过数据的键访问每个值，例如 `<?php echo $name; ?>`。

除了向 `view` 辅助函数传递完整的数据数组之外，您还可以使用 `with` 方法向视图添加单独的数据。`with` 方法会返回一个视图对象实例，因此您可以在返回视图之前继续链式调用其他方法：

```php
return view('greeting')
    ->with('name', 'Victoria')
    ->with('occupation', 'Astronaut');
```

### 与所有视图共享数据



有时，您可能需要与应用程序渲染的所有视图共享数据。您可以使用 `View` 门面的 `share` 方法来实现这一点。通常，您应该将对 `share` 方法的调用放置在服务提供者的 `boot` 方法中。您可以自由地将它们添加到 `App\Providers\AppServiceProvider` 类中，或者生成一个单独的服务提供者来存放它们：

```php
<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 注册应用程序服务。
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 启动任何应用程序服务。
     */
    public function boot(): void
    {
        View::share('key', 'value');
    }
}
```

## 视图组合器

视图组合器（View composers）是在视图渲染时调用的回调函数或类方法。如果您有一些数据，希望在每次渲染某个视图时都绑定到该视图，那么视图组合器可以帮助您将这部分逻辑组织到一个统一的位置。

如果您的应用程序中有多个路由或控制器返回相同的视图，并且该视图始终需要某些特定数据，那么视图组合器会特别有用。

通常，视图组合器会在应用程序的某个[服务提供者](/docs/laravel/13.x/providers)中进行注册。在这个示例中，我们假设 `App\Providers\AppServiceProvider` 将负责存放这些逻辑。

我们将使用 `View` 门面的 `composer` 方法来注册视图组合器。Laravel 不会为基于类的视图组合器提供默认目录，因此您可以按照自己的方式组织它们。例如，您可以创建一个 `app/View/Composers` 目录，用于存放应用程序中的所有视图组合器：

```php
<?php

namespace App\Providers;

use App\View\Composers\ProfileComposer;
use Illuminate\Support\Facades;
use Illuminate\Support\ServiceProvider;
use Illuminate\View\View;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 注册应用程序服务。
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 启动任何应用程序服务。
     */
    public function boot(): void
    {
        // 使用基于类的组合器...
        Facades\View::composer('profile', ProfileComposer::class);

        // 使用基于闭包的组合器...
        Facades\View::composer('welcome', function (View $view) {
            // ...
        });

        Facades\View::composer('dashboard', function (View $view) {
            // ...
        });
    }
}
```



现在我们已经注册了组合器（composer），每次渲染 `profile` 视图时，`App\View\Composers\ProfileComposer` 类的 `compose` 方法都会被执行。下面来看一个组合器类的示例：

```php
<?php

namespace App\View\Composers;

use App\Repositories\UserRepository;
use Illuminate\View\View;

class ProfileComposer
{
    /**
     * 创建一个新的个人资料组合器。
     */
    public function __construct(
        protected UserRepository $users,
    ) {}

    /**
     * 将数据绑定到视图。
     */
    public function compose(View $view): void
    {
        $view->with('count', $this->users->count());
    }
}
```

正如您所看到的，所有视图组合器都会通过[服务容器](/docs/laravel/13.x/container)进行解析，因此您可以在组合器的构造函数中通过类型提示声明任何所需的依赖项。

#### 将组合器附加到多个视图

您可以通过将视图数组作为 `composer` 方法的第一个参数传递，将一个视图组合器同时附加到多个视图：

```php
use App\Views\Composers\MultiComposer;
use Illuminate\Support\Facades\View;

View::composer(
    ['profile', 'dashboard'],
    MultiComposer::class
);
```

`composer` 方法还支持使用 `*` 字符作为通配符，这允许您将组合器附加到所有视图：

```php
use Illuminate\Support\Facades;
use Illuminate\View\View;

Facades\View::composer('*', function (View $view) {
    // ...
});
```

### 视图创建器

视图“创建器”（creators）与视图组合器非常相似；但是，它们会在视图实例化后立即执行，而不是等待视图即将渲染时执行。要注册一个视图创建器，请使用 `creator` 方法：

```php
use App\View\Creators\ProfileCreator;
use Illuminate\Support\Facades\View;

View::creator('profile', ProfileCreator::class);
```



## 优化视图

默认情况下，Blade 模板视图会按需进行编译。当执行一个会渲染视图的请求时，Laravel 会判断该视图是否存在已编译版本。如果文件存在，Laravel 会进一步判断未编译的视图是否比已编译的视图更新。如果已编译视图不存在，或者未编译视图已被修改，Laravel 将重新编译该视图。

在请求过程中编译视图可能会对性能产生轻微的负面影响，因此 Laravel 提供了 `view:cache` Artisan 命令，用于预编译应用程序使用的所有视图。为了提高性能，您可能希望将此命令作为部署流程的一部分执行：

```shell
php artisan view:cache
```

您可以使用 `view:clear` 命令清除视图缓存：

```shell
php artisan view:clear
```

