mcpField
L
laravel-inertia-vue

laravel-inertia-vue

github.com/jasim-k开发0157 次安装33 周前更新
代码仓库

关于 laravel-inertia-vue

laravel-inertia-vue 是面向 Laravel、Inertia.js 和 Vue 3 单体应用开发的技能,提供实践模式。其分优先级规则覆盖页面、表单、导航、共享数据、布局、上传及进阶界面模式。

主要功能

  1. 01六类共 24 条规则
  2. 02类型化 Inertia 页面组件
  3. 03表单与验证模式
  4. 04导航和共享数据指南
  5. 05持久化与嵌套布局
  6. 06上传及进阶页面模式

适用场景

  1. 01构建类型化 Inertia 页面组件
  2. 02处理表单提交与验证
  3. 03共享认证信息和闪存数据
  4. 04实现上传、轮询或无限滚动

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jasim-k/laravel-agent-skills --skill laravel-inertia-vue

安装后在 Claude Code 中输入/laravel-inertia-vue确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

AGENTS.md
metadata.json
README.md
rules/
_sections.md
_template.md
form-dirty-tracking.md
form-file-uploads.md
form-progress-indicator.md
form-reset-handling.md
form-transform-data.md
form-useform-basic.md
form-useform-hook.md
form-validation-errors.md
layout-persistent.md
nav-external-links.md
nav-link-component.md
nav-preserve-state.md
nav-programmatic.md
nav-replace-history.md
page-component-structure.md
page-default-layout.md
page-head-management.md
page-partial-reloads.md
page-props-typing.md
page-scroll-preservation.md
shared-app-config.md
shared-auth-user.md
shared-flash-messages.md
shared-ziggy-routes.md

详细介绍

Laravel + Inertia.js + Vue 3

使用 Laravel、Inertia.js 和 Vue 3 构建现代单体应用的全面模式。包含 30 多条规则,助力流畅的全栈开发。

适用场景

在以下情况下参考这些指南:

  • 使用 Vue 3 创建 Inertia 页面组件
  • 使用 useForm 组合式函数处理表单
  • 管理共享数据和身份验证
  • 实现持久化布局
  • 在页面间导航

按优先级划分的规则类别

优先级类别影响前缀
1页面组件严重page-
2表单与验证严重form-
3导航与链接高nav-
4共享数据高shared-
5布局中layout-
6文件上传中upload-
7高级模式低advanced-

快速参考

1. 页面组件(严重)
  • page-props-typing - 为 Laravel 页面属性指定类型
  • page-component-structure - 标准页面组件模式
  • page-head-management - 使用 Head 管理标题和元标签
  • page-default-layout - 为页面指定布局
2. 表单与验证(严重)
  • form-useform-basic - useForm 基本用法
  • form-validation-errors - 显示 Laravel 验证错误
  • form-processing-state - 处理表单提交状态
  • form-reset-preserve - 重置或保留表单数据
  • form-transform - 提交前转换数据
3. 导航与链接(高)
  • nav-link-component - 使用 Link 进行导航
  • nav-preserve-state - 保留滚动位置和状态
  • nav-partial-reloads - 仅重新加载发生变化的内容
  • nav-replace-history - 替换或推入历史记录
4. 共享数据(高)
  • shared-auth-user - 访问已验证的用户
  • shared-flash-messages - 处理闪现消息
  • shared-global-props - 访问全局属性
  • shared-typescript - 为共享数据指定类型
5. 布局(中)
  • layout-persistent - 持久化布局模式
  • layout-nested - 嵌套布局
  • layout-default - 默认布局指定
  • layout-conditional - 条件布局
6. 文件上传(中)
  • upload-basic - 基本文件上传
  • upload-progress - 跟踪上传进度
  • upload-multiple - 多文件上传
7. 高级模式(低)
  • advanced-polling - 实时轮询
  • advanced-prefetch - 预取页面
  • advanced-modal-pages - 将模态框用作页面
  • advanced-infinite-scroll - 无限滚动

核心模式

使用 TypeScript 的页面组件

<script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3'

interface Post {
  id: number
  title: string
  excerpt: string
  created_at: string
  author: {
    id: number
    name: string
  }
}

interface Props {
  posts: {
    data: Post[]
    links: { url: string | null; label: string; active: boolean }[]
  }
  filters: {
    search?: string
  }
}

const props = defineProps<Props>()
</script>

<template>
  <Head title="Posts" />

  <div class="container mx-auto py-8">
    <h1 class="text-2xl font-bold mb-6">Posts</h1>

    <div class="space-y-4">
      <article
        v-for="post in props.posts.data"
        :key="post.id"
        class="p-4 bg-white rounded-lg shadow"
      >
        <Link :href="route('posts.show', post.id)">
          <h2 class="text-xl font-semibold hover:text-blue-600">
            {{ post.title }}
          </h2>
        </Link>
        <p class="text-gray-600 mt-2">{{ post.excerpt }}</p>
        <p class="text-sm text-gray-400 mt-2">By {{ post.author.name }}</p>
      </article>
    </div>
  </div>
</template>
使用 useForm 的表单

<script setup lang="ts">
import { Head, Link, useForm } from '@inertiajs/vue3'

interface Category {
  id: number
  name: string
}

interface Props {
  categories: Category[]
}

const props = defineProps<Props>()

const form = useForm({
  title: '',
  body: '',
  category_id: '',
})

function submit() {
  form.post(route('posts.store'), {
    onSuccess: () => form.reset(),
  })
}
</script>

<template>
  <Head title="Create Post" />

  <form @submit.prevent="submit" class="max-w-2xl mx-auto py-8">
    <div class="mb-4">
      <label for="title" class="block font-medium mb-1">Title</label>
      <input
        id="title"
        v-model="form.title"
        type="text"
        class="w-full border rounded px-3 py-2"
      />
      <p v-if="form.errors.title" class="text-red-500 text-sm mt-1">
        {{ form.errors.title }}
      </p>
    </div>

    <div class="mb-4">
      <label for="category" class="block font-medium mb-1">Category</label>
      <select
        id="category"
        v-model="form.category_id"
        class="w-full border rounded px-3 py-2"
      >
        <option value="">Select a category</option>
        <option v-for="cat in props.categories" :key="cat.id" :value="cat.id">
          {{ cat.name }}
        </option>
      </select>
      <p v-if="form.errors.category_id" class="text-red-500 text-sm mt-1">
        {{ form.errors.category_id }}
      </p>
    </div>

    <div class="mb-4">
      <label for="body" class="block font-medium mb-1">Content</label>
      <textarea
        id="body"
        v-model="form.body"
        rows="10"
        class="w-full border rounded px-3 py-2"
      />
      <p v-if="form.errors.body" class="text-red-500 text-sm mt-1">
        {{ form.errors.body }}
      </p>
    </div>

    <div class="flex gap-4">
      <button
        type="submit"
        :disabled="form.processing"
        class="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
      >
        {{ form.processing ? 'Creating...' : 'Create Post' }}
      </button>

      <Link :href="route('posts.index')" class="px-4 py-2 border rounded">
        Cancel
      </Link>
    </div>
  </form>
</template>
持久化布局

<script setup lang="ts">
import { Link, usePage } from '@inertiajs/vue3'
import { computed } from 'vue'

const page = usePage()
const auth = computed(() => page.props.auth as { user: { name: string } })
</script>

<template>
  <div class="min-h-screen bg-gray-100">
    <nav class="bg-white shadow">
      <div class="container mx-auto px-4 py-3 flex justify-between">
        <Link href="/" class="font-bold">My App</Link>
        <span>Welcome, {{ auth.user.name }}</span>
      </div>
    </nav>

    <main class="container mx-auto px-4 py-8">
      <slot />
    </main>
  </div>
</template>

<script setup lang="ts">
import AppLayout from '@/Layouts/AppLayout.vue'

defineOptions({ layout: AppLayout })
</script>

<template>
  <h1>Dashboard</h1>
</template>
Laravel 控制器
<?php

namespace App\Http\Controllers;

use App\Http\Requests\StorePostRequest;
use App\Models\Post;
use App\Models\Category;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class PostController extends Controller
{
    public function index(): Response
    {
        return Inertia::render('Posts/Index', [
            'posts' => Post::with('author:id,name')
                ->latest()
                ->paginate(10),
            'filters' => request()->only('search'),
        ]);
    }

    public function create(): Response
    {
        return Inertia::render('Posts/Create', [
            'categories' => Category::all(['id', 'name']),
        ]);
    }

    public function store(StorePostRequest $request): RedirectResponse
    {
        $post = Post::create([
            ...$request->validated(),
            'user_id' => auth()->id(),
        ]);

        return redirect()
            ->route('posts.show', $post)
            ->with('success', 'Post created successfully.');
    }

    public function show(Post $post): Response
    {
        return Inertia::render('Posts/Show', [
            'post' => $post->load('author', 'category'),
        ]);
    }
}
共享数据(HandleInertiaRequests)
<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'auth' => [
                'user' => $request->user() ? [
                    'id' => $request->user()->id,
                    'name' => $request->user()->name,
                    'email' => $request->user()->email,
                ] : null,
            ],
            'flash' => [
                'success' => $request->session()->get('success'),
                'error' => $request->session()->get('error'),
            ],
        ]);
    }
}
闪现消息组件

<script setup lang="ts">
import { usePage } from '@inertiajs/vue3'
import { computed, ref, watch } from 'vue'

const page = usePage()
const flash = computed(() => page.props.flash as { success?: string; error?: string })
const visible = ref(false)
let timer: ReturnType<typeof setTimeout> | null = null

watch(flash, (newFlash) => {
  if (newFlash.success || newFlash.error) {
    visible.value = true
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      visible.value = false
    }, 3000)
  }
}, { deep: true })
</script>

<template>
  <div v-if="visible" class="fixed top-4 right-4 z-50">
    <div
      v-if="flash.success"
      class="bg-green-500 text-white px-4 py-2 rounded shadow"
    >
      {{ flash.success }}
    </div>
    <div
      v-if="flash.error"
      class="bg-red-500 text-white px-4 py-2 rounded shadow"
    >
      {{ flash.error }}
    </div>
  </div>
</template>

使用方法

阅读各条规则文件,了解详细说明和代码示例:

rules/form-useform-basic.md
rules/page-props-typing.md
rules/layout-persistent.md

项目结构

laravel-inertia-vue/
├── SKILL.md                 # This file - overview and examples
├── README.md                # Quick reference guide
├── AGENTS.md                # Integration guide for AI agents
├── metadata.json            # Skill metadata and references
└── rules/
    ├── _sections.md         # Rule categories and priorities
    ├── _template.md         # Template for new rules
    ├── page-*.md            # Page component patterns (6 rules)
    ├── form-*.md            # Form handling patterns (8 rules)
    ├── nav-*.md             # Navigation patterns (5 rules)
    ├── shared-*.md          # Shared data patterns (4 rules)
    └── layout-*.md          # Layout patterns (1 rule)

参考资料

许可证

MIT 许可证。本技能按原样提供,用于教育和开发目的。

元数据

  • 版本:1.0.0
  • 最近更新:2026-03-17
  • 维护者:Jasim K
  • 规则数量:6 个类别,共 24 条规则
  • 技术栈:Laravel 12+、Inertia.js 2.0+、Vue 3.3+、TypeScript 5+

评论

支持 Markdown