monoeq/kirby-inertia

Kirby Inertia 适配器

安装: 70

依赖项: 0

建议者: 0

安全性: 0

星星: 34

关注者: 3

分支: 1

开放问题: 2

类型:kirby-plugin

v1.0.1 2020-06-30 02:23 UTC

This package is auto-updated.

Last update: 2024-09-11 03:34:57 UTC


README

Inertia.js 是 Kirby 3 的适配器。

Inertia 允许您使用 JavaScript (React、Vue 和 Svelte) 构建前端,同时让服务器(在本例中为 Kirby)处理路由和数据处理。将其视为构建一个普通的 Kirby 网站,但前端使用 JavaScript 渲染。

工作原理

基本思想是当在浏览器中加载您的网站时,Kirby 提供一个包含内联 JSON 页面数据的 HTML 页面,以便您的 JavaScript 应用程序可以渲染页面。当您导航到不同的页面时,将带有 X-Inertia 标头的请求发送到 Kirby,通知 Kirby 只返回页面 JSON,而不是完整的 HTML 响应。您的 JavaScript 应用程序会接收到这些数据并渲染每个新页面。您可以在 Inertia 网站上阅读更多关于其工作原理的内容。

📌 本 README 不会介绍 Inertia 的工作原理或如何构建前端。它只是概述了实现以将 Kirby 用作 Inertia 后端的核心功能。

设置

安装 之后,您需要做的最基本的事情是定义一个 default.php 模板

<!DOCTYPE html>
<html>
<head>
  <title><?= $site->title() ?></title>
  <?= css('assets/css/site.css'); /* Your site’s css */ ?>
</head>
<body>
<?php snippet('inertia') ?>
<?= js('assets/js/site.js'); /* Your site’s js */ ?>
</body>
</html>

包含的 inertia 片段 仅渲染一个带有当前页面数据编码为 JSON 的应用程序外壳

<div id="app" data-page="{}"></div>

在此阶段,您可以继续构建您的 Inertia 前端。如果您在浏览器中访问您的网站(并查看源代码),您将看到包含页面数据的应用程序外壳。如果您使用带有 X-Inertia 标头的相同 URL 请求(使用 wget/curl 或 Postman 测试),将返回一个 JSON 响应。

创建响应

在 Kirby 中创建 Inertia 响应,使用 Kirby 控制器。与典型 Kirby 控制器唯一的区别是您返回一个 Inertia::render 函数,而不是数组。此插件为您分配了一个 default.php 控制器

return function ($page, $site, $kirby) {
  return Inertia::render(
    $page->intendedTemplate(), 
    $page->toArray()
  );
};

第一个参数指定了您的 JavaScript 应用程序应渲染的视图名称,第二个参数是页面数据。在本例中,我们使用 $page->intendedTemplate() 作为视图名称,并使用 $page->toArray() 方法传递页面数据。

以下是一个具有更具体控制的示例 Controller

return function ($page, $site, $kirby) {
  return Inertia::render('TemplateName', [
    'title' => $page->title()->value(),
    'date' => $page->date()->value(),
    'thumbnail' => $page->thumbnail()->toFile()->url(),
    'content' => $page->text()->kirbytext()
  ]);
};

Inertia 功能

以下部分概述了如何在 Kirby 中使用一些 Inertia 功能,因为它们与 Laravel 适配器略有不同。

延迟评估

延迟评估 和部分数据按预期工作,只需将数据包裹在闭包中即可

return function ($page, $site, $kirby) {
  return Inertia::render('TemplateName', [
    'title' => $page->title()->value(),
    'lazyProp' => function () use ($page) {
      return $page->children()->toArray();
    }
  ]);
};

共享数据

与 Laravel 适配器不同,Kirby 中的共享数据是在您的config.php中定义的。您可以将共享数据定义为数组(值可以是闭包)或定义为返回数组的闭包。

'monoeq.inertia.shared' => [
  "prop" => "value",
  "beep" => function () {
    return "boop";
  }
]
'monoeq.inertia.shared' => function () {
  return [
    "prop" => "value"
  ];
}

表单处理

在 Kirby 控制器中处理表单,就像您通常做的那样。只需确保您按照 Inertia 文档中的说明重定向到视图

return function ($page, $site, $kirby) {
  
  // Form Handling
  if (kirby()->request()->method() === 'POST') {
    $kirby->impersonate('kirby');
    $page->changeTitle(get('title', ''));
    go($page); // <- Redirect back to GET request for Inertia
  }

  return Inertia::render(
    $page->intendedTemplate(), 
    $page->toArray()
  );
};

错误处理

您还希望在控制器中处理错误。包含了一个InertiaSession辅助器,用于将数据传递到 Kirby 会话,然后您可以在共享数据中获取这些数据。请在此处查看示例。

根模板数据

您可以通过$inertia变量访问 Kirby 模板中的数据。例如:$inertia['prop']

使用视图数据

Kirby Inertia 没有提供withViewData方法,相反,您可以在调用Inertia::render时传递第三个参数。这就像正常控制器行为一样将数据传递到 kirby 模板。

return function ($page, $site, $kirby) {
  return Inertia::render(
    $page->intendedTemplate(), 
    $page->toArray(),
    [ 'meta' => 'hello' ]
  );
};

// In your template:
<?= $meta ?>

会话数据

包含了一个InertiaSession辅助器,用于将会话数据传递到您的 Inertia 视图。这对于服务器端验证闪存消息非常有用,类似于 Laravel 的Inertia::share。您可以在设置共享数据时处理 Inertia 会话数据,在config.php中。

return [
  'monoeq.inertia.shared' => [
    'messages' => function () {
      // pull() fetches any session data stored under messages, and then wipes it
      return InertiaSession::pull('messages');
    },
    'errors' => function () {
      // pull() fetches any session data stored under errors, and then wipes it
      return InertiaSession::pull('errors');
    }
  ]
];

所以,您可以在表单控制器中使用此辅助器,如下所示

return function ($page, $site, $kirby) {
  
  // Form Handling
  if (kirby()->request()->method() === 'POST') {
    try {
      $kirby->impersonate('kirby');
      $page->changeTitle(get('title', ''));
      InertiaSession::append('messages', 'Thank You!');
    } catch (Exception $e) {
      InertiaSession::append('errors', $e->getMessage());
      // or if you want to have named errors
      // InertiaSession::merge('errors', [ 'title' => $e->getMessage() ]);  
    }
    go($page); // <- Redirect back to GET request for Inertia
  }

  return Inertia::render(
    $page->intendedTemplate(), 
    $page->toArray()
  );
};

然后,在您的 JavaScript 视图中,您可以获取这些数据

<div v-if="$page.messages">{{ $page.messages }}</div>
<div v-if="$page.errors">{{ $page.errors }}</div>

配置

config.php 中设置版本控制共享数据

return [
  'monoeq.inertia.version' => '1.0',
  'monoeq.inertia.shared' => [
    'site' => function () {
      return [
        'title' => site()->title()->value()
      ];
    }
  ]
];

类 API

Inertia

Inertia::render($name, $data, $viewData)

从您的 Kirby 控制器返回以渲染 Inertia 响应。

InertiaSession

kirby()->session()周围包装的类,用于将数据传递到您的 Inertia 视图。底层使用inertia命名空间,以避免与其他 Kirby 会话数据冲突。

InertiaSession::set($key, $value)

包装了$session->set()

InertiaSession::append($key, $value)

将值追加到指定的键(如果没有定义,则设置键)。

InertiaSession::append('messages', 'beep');
InertiaSession::append('messages', 'boop');
InertiaSession::get('messages'); // => ['beep', 'boop']

InertiaSession::merge($key, $value)

将值合并到指定的键(如果没有定义,则设置键)。

InertiaSession::merge('messages', [ 'beep' => 'boop' ]);
InertiaSession::merge('messages', [ 'bleep' => 'bloop' ]);
InertiaSession::get('messages'); // => [ 'beep' => 'boop', 'bleep' => 'bloop' ]

InertiaSession::get($key)

包装了$session->get()

InertiaSession::pull($key)

包装了$session->pull()

InertiaSession::remove($key)

包装了$session->remove()

安装

下载

下载并将此存储库复制到 /site/plugins/kirby-inertia

Git 子模块

git submodule add https://github.com/monoeq/kirby-inertia.git site/plugins/kirby-inertia

Composer

composer require monoeq/kirby-inertia

其他注意事项

自动模板

在 Kirby 中,通常需要为控制器创建一个实际的模板文件。但是当使用 Inertia 时,通常只需要 default.php 模板。作为一个辅助工具,这个插件会自动将任何没有匹配模板文件的控制器文件分配给 default.php,这样您就可以只创建控制器而不必担心创建模板。

前端示例

有关如何构建 Inertia 前端的详细信息,请参阅 Inertia.js 文档,但这里有一个使用 Vue 的基本示例。

app.js

查看代码
import { InertiaApp } from '@inertiajs/inertia-vue'
import Vue from 'vue'
import 'nprogress/nprogress.css'

Vue.use(InertiaApp)

const app = document.getElementById('app')

// Include templates here
const templates = {
  'default': require('./templates/default').default
}

new Vue({
  render: h => h(InertiaApp, {
    props: {
      initialPage: JSON.parse(app.dataset.page),
      // Falls back to default template, Kirby-style
      resolveComponent: name => templates[name] || templates['default']
    },
  }),
}).$mount(app)

templates/default.vue

查看代码
<template>
  <div>{{ content.title }}</div>
</template>

<script>
  export default {
    props: {
      content: Object
    }
  }
</script>

待办事项

  • 缓存
    • 启用 Kirby 缓存将目前破坏 Inertia 功能。

致谢