显示侧边栏
指南
隐藏侧边栏

原则

Flux 不是一 UI Blade 组件,而是一个由这些组件组成的系统。该系统的设计受一系列原则引导;当你遵循这些原则时,将获得更干净、更具创造性且更直观的应用构建体验。

简单

最重要的是,在语法、实现和视觉上,Flux 追求的首要品质就是简洁。
例如,看看用 Flux 编写的一个基础输入框:
<flux:input wire:model="email" label="Email" />
它很简单
再看看当不重视简洁时,同一个输入框会变成怎样的反面示例:
<flux:form.field>    <flux:form.field.label>Email</flux:form.field.label>    <div>        <flux:form.field.text-input wire:model="email" />    </div>    @error('email')        <p class="mt-2 text-red-500 dark:text-red-400 text-xs">{{ $message }}</p>    @enderror</flux:form.field>
这就是一团

复杂度

当然,简洁是有取舍的。对于一个“做了太多事”的单一组件来说,要定制它的细节部分会更困难。
这就是为什么 Flux 为那些过于简单的组件提供可组合的替代方案。
回到前面这个输入框的版本:
<flux:input wire:model="email" label="Email" />
如果你需要更强的可控性,可以从更小的部件开始手动组合出这个表单字段:
<flux:field>    <flux:label>Email</flux:label>    <flux:input wire:model="email" />    <flux:error name="email" /></flux:field>
这样你就能两全其美:常见场景下拥有简短精炼的语法,同时也能在需要时对每个部分进行细粒度的定制。

友好性

在可能的情况下,Flux 为组件选择更熟悉、友好的名称,而不是过于技术化的术语。
例如,你不会在 Flux 中看到 “form controls” 这样的词。大多数开发者更倾向于使用更直白的 “form inputs”。
再比如,将可折叠区块称为 “accordion”,而不是更为严格的 “disclosure”。尽管 “disclosure” 在 UI 模式上更准确,但 “accordion” 在应用开发者中更常用。

组合式

在“简单”之后,可组合性是第二重要的价值。理想情况下,你掌握少量核心组件,然后将它们自由拼搭以创建(或组合)更健壮的组件。
例如,下面是 Flux 中常见的按钮组件:
<flux:button>Options</flux:button>
如果你想用这个按钮来触发下拉菜单,只需将它包裹在 <flux:dropdown> 中:
<flux:dropdown>    <flux:button>Options</flux:button>    <flux:navmenu>        <!-- ... -->    </flux:navmenu></flux:dropdown>
许多其他库会把你限制在更刚性的组件形状中,不允许在下拉菜单里使用简单按钮,而是强迫你使用更具规定性的替代品,如 <flux:dropdown.button>
因为组合式是优先事项,你可以把这个导航下拉改造成一个包含子菜单、可勾选项且支持键盘操作的“系统菜单”。只需将 navmenu 替换为 menu 即可:
<flux:dropdown>    <flux:button>Options</flux:button>    <flux:menu>        <!-- ... -->    </flux:menu></flux:dropdown>
由于 <flux:menu> 本身就是一个独立组件,你也可以结合 <flux:context> 组件,用于在右键时打开上下文菜单:
<flux:context>    <flux:button>Options</flux:button>    <flux:menu>        <!-- ... -->    </flux:menu></flux:context>
就是组合的力量:能够将彼此独立的组件组合成全新且更强大的组件。

一致性

命名、组件结构等不一致会带来困惑与挫败,削弱系统的直观性。
因此,你会在 Flux 中看到大量重复且统一的语法模式。
一个简单的例子是:许多组件使用 “heading” 一词,而不是 “title” 或 “name”。
这样,你无需反复猜测或查找,更容易记住组件相关术语。
以下是几个使用 “heading” 的 Flux 组件示例:
<flux:heading>...</flux:heading><flux:menu.submenu heading="..."><flux:accordion.heading>...</flux:accordion.heading>

简洁性

继“简单”之后,“简洁”同样是重点。Flux 力求在不牺牲上述任何原则的前提下尽可能简短。
总体而言,我们在 Flux 语法中避免使用需要连字符的复合词,也避免过深的点号分隔的嵌套命名。
例如,我们使用更简单的 “input”,而不是 “text-input”、“input-text”、“form-input” 或 “form-control”:
<flux:input>
组合式也有助于追求简洁。看看下面的下拉菜单组件:
<flux:dropdown>    <flux:button>Options</flux:button>    <flux:menu>        <!-- ... -->    </flux:menu></flux:dropdown>
请注意,这个下拉组件使用了简单的单词命名。
想象一下,如果不那么重视可组合性与简洁性,可能会长这样:
<flux:dropdown-menu>    <flux:dropdown-menu.button>Options</flux:dropdown-menu.button>    <flux:dropdown-menu.items>        <!-- ... -->    </flux:dropdown-menu.items></flux:dropdown-menu>

善用浏览器

现代浏览器能力强大。Flux 致力于充分利用这些能力。
当你使用浏览器原生特性时,你依赖的是开箱即用且可靠的行为,无需下载任何 JavaScript 库。
例如,你在 Flux 中看到的下拉菜单(popover)通常在底层使用了 popover 属性。这是一个相对较新但支持度很高的特性,能解决手写下拉菜单时经常遇到的诸多问题:
<div popover>    <!-- ... --></div>
另一个例子是:使用原生的 <dialog> 元素来实现模态框,而不是手写一套:
<dialog>    <!-- ... --></dialog>
使用原生的 <dialog> 元素,你可以开箱即用地获得更一致、更可靠的模态体验,例如焦点管理、可访问性以及键盘导航等。

善用 CSS

CSS 正逐渐成为编写可组合设计系统的强大工具。随着 :has():not():where() 等新特性的出现,以前需要 JavaScript 的事情,现在仅用 CSS 就能完成。
当你查看某个 Flux 组件的源码时,可能会注意到我们使用了一些复杂的 Tailwind 工具类。
这是对复杂度的一种取舍。在 Flux 中,只要某个问题可以用 CSS 解决,就不会用 PHP 或 JavaScript,而是用 CSS。
比如,看看 flux:command.input 组件中,当输入框获得焦点时搜索图标如何改变颜色:
<flux:command.input placeholder="Search..." />
在浏览器中渲染后,当输入框聚焦时,搜索图标会变得更深。这种优雅的交互无需任何 JavaScript。
这是通过 CSS 的 :has() 选择器实现的。下面是组件中实际使用到的 Tailwind 工具类:
[&:has(+input:focus)]:text-zinc-800
上述选择器会匹配到“拥有一个处于焦点状态的兄弟 input 元素”的任何元素,并将其文字颜色变得更深。这是一个无需额外 JavaScript、利用现代 CSS 增强用户体验的简洁而有力的示例。

我们负责样式,你负责留白

总体上,Flux 开箱即用地提供样式,而把间距交给你。更直白地说:我们提供内边距,你来决定外边距。
例如,看看下面这个“创建账户”的表单:
<form wire:submit="createAccount">    <div class="mb-6">        <flux:heading>Create an account</flux:heading>        <flux:text class="mt-2">We're excited to have you on board.</flux:text>    </div>    <flux:input class="mb-6" label="Email" wire:model="email" />    <div class="mb-6 flex *:w-1/2 gap-4">        <flux:input label="Password" wire:model="password" />        <flux:input label="Confirm password" wire:model="password_confirmation" />    </div>    <flux:button type="submit" variant="primary">Create account</flux:button></form>
你会注意到:Flux 负责各个组件的样式,但将间距与布局留给你掌控。
之所以采用这种方式,是因为间距高度依赖上下文,而样式则相对独立。如果我们把间距写死在 Flux 中,你可能不得不频繁覆盖,或者更糟的是保留它从而让应用看起来支离破碎。
自行管理间距与布局会稍微多花一点精力,但灵活性带来的回报非常值得。
© 2025 FluxProMax™. All Rights Reserved.

备案号:皖ICP备13019729号-11