关于 inertia-coder
inertia-coder 是用于开发 Inertia.js 单页应用的技能,搭配 Rails 后端以及 React、Vue 或 Svelte。内容涵盖安装、页面组件、表单、共享属性和文件上传,并沿用服务端路由。
主要功能
- 01Rails 与 Inertia.js 安装配置
- 02React、Vue 和 Svelte 页面模式
- 03使用 useForm 处理表单
- 04共享属性与 flash 消息
- 05带进度跟踪的文件上传
适用场景
- 01搭建 Inertia.js Rails 应用
- 02使用服务端提供的属性构建页面
- 03处理表单和文件上传
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill inertia-coder安装后在 Claude Code 中输入/inertia-coder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/react-patterns.mdsvelte-patterns.mdvue-patterns.md详细介绍
Inertia.js + Rails
使用 Inertia.js、React/Vue/Svelte 和 Rails 后端构建现代单页应用。
何时使用此技能
- 在 Rails 中设置 Inertia.js
- 创建 Inertia 页面组件
- 使用 useForm hook 处理表单
- 管理共享 props 和闪存消息
- 无需复杂 API 即可进行客户端路由
- 跟踪文件上传进度
什么是 Inertia.js?
Inertia.js 允许你使用经典的服务端路由和控制器构建 SPA。
| 方案 | 优点 | 缺点 |
|---|---|---|
| 传统 Rails 视图 | 简单,由服务器渲染 | 交互性有限 |
| Rails API + React SPA | 完整的 SPA 体验 | 路由重复,状态复杂 |
| Inertia.js | SPA + 服务端路由 | 两全其美 |
快速设置
# Gemfile
gem 'inertia_rails'
gem 'vite_rails'
bundle install
rails inertia:install # Choose: React, Vue, or Svelte
# config/initializers/inertia_rails.rb
InertiaRails.configure do |config|
config.version = ViteRuby.digest
config.share do |controller|
{
auth: {
user: controller.current_user&.as_json(only: [:id, :name, :email])
},
flash: controller.flash.to_hash
}
end
end
控制器模式
class ArticlesController < ApplicationController
def index
articles = Article.published.order(created_at: :desc)
render inertia: 'Articles/Index', props: {
articles: articles.as_json(only: [:id, :title, :excerpt])
}
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to article_path(@article), notice: 'Article created'
else
redirect_to new_article_path, inertia: { errors: @article.errors }
end
end
end
React 页面组件
// app/frontend/pages/Articles/Index.jsx
import { Link } from '@inertiajs/react'
export default function Index({ articles }) {
return (
<div>
<h1>Articles</h1>
{articles.map(article => (
<Link key={article.id} href={`/articles/${article.id}`}>
<h2>{article.title}</h2>
</Link>
))}
</div>
)
}
使用 useForm 处理表单
import { useForm } from '@inertiajs/react'
export default function New() {
const { data, setData, post, processing, errors } = useForm({
title: '',
body: ''
})
function handleSubmit(e) {
e.preventDefault()
post('/articles')
}
return (
<form onSubmit={handleSubmit}>
<input
value={data.title}
onChange={e => setData('title', e.target.value)}
/>
{errors.title && <div className="error">{errors.title}</div>}
<textarea
value={data.body}
onChange={e => setData('body', e.target.value)}
/>
{errors.body && <div className="error">{errors.body}</div>}
<button disabled={processing}>
{processing ? 'Creating...' : 'Create'}
</button>
</form>
)
}
共享布局
// app/frontend/layouts/AppLayout.jsx
import { Link, usePage } from '@inertiajs/react'
export default function AppLayout({ children }) {
const { auth, flash } = usePage().props
return (
<div>
<nav>
<Link href="/">Home</Link>
{auth.user ? (
<Link href="/logout" method="delete">Logout</Link>
) : (
<Link href="/login">Login</Link>
)}
</nav>
{flash.success && <div className="alert-success">{flash.success}</div>}
<main>{children}</main>
</div>
)
}
// Assign layout to page
Index.layout = page => <AppLayout>{page}</AppLayout>
文件上传
import { useForm } from '@inertiajs/react'
const { data, setData, post, progress } = useForm({
avatar: null
})
<input
type="file"
onChange={e => setData('avatar', e.target.files[0])}
/>
{progress && <progress value={progress.percentage} max="100" />}
<button onClick={() => post('/profile/avatar', { forceFormData: true })}>
Upload
</button>
最佳实践
应该做
- 使用
<Link>而不是<a>标签 - 通过 config 共享常用数据(auth、flash)
- 在服务器端进行验证——客户端仅用于提升用户体验
- 使用
processing显示加载状态 - 使用布局保持导航一致
不应该做
- 不要使用
window.location——这会破坏 SPA - 不要创建 REST API——Inertia 不需要它们
- 不要在客户端获取数据——服务器会提供 props
- 不要绕过 Inertia 路由器——这会破坏行为
详细参考
有关特定框架的模式:
references/react-patterns.md- React hooks、TypeScript 和高级模式references/vue-patterns.md- Vue 3 Composition API 模式references/svelte-patterns.md- Svelte stores 和响应式模式
评论
支持 Markdown