
Neos.Fusion:Tag和Neos.Fusion:Join,使得代码变得非常难以阅读和维护。尤其是在处理多层HTML结构时,那种层层嵌套的感觉,让我感觉不像在编写视图组件,更像是在堆砌配置项。这不仅拖慢了开发进度,也让团队协作变得更加困难。Composer在线学习地址:学习地址
幸运的是,Composer生态为我们带来了解决方案。今天,我想向大家介绍一个强大的Composer包——neos/fusion-afx,它彻底改变了我编写Neos Fusion组件的方式,让Fusion代码变得前所未有的简洁和优雅。
neos/fusion-afx 是什么?
neos/fusion-afx 提供了一种受JSX启发的紧凑语法,让我们可以直接在Fusion文件中以类似XML的方式定义组件结构。你可以把它想象成是Fusion世界的JSX——它是一个Fusion预处理器,能将这种简洁的AFX语法在解析时转换为纯粹的Fusion代码,并进行缓存,从而在运行时保持高效。
它的核心优势在于:
- 无需独立模板文件:所有视图逻辑直接在Fusion文件中完成,减少文件切换。
- 增强可读性:以更直观的标签形式展现组件结构,一目了然。
-
强大的可扩展性:由于最终生成的是纯Fusion代码,你仍然可以利用Fusion的强大机制(如
@override)对其进行扩展和重写。
如何安装?
使用Composer安装neos/fusion-afx非常简单。只需在你的Neos项目根目录运行以下命令:
composer require neos/fusion-afx
告别冗长,拥抱简洁
让我们通过一个实际例子来看看neos/fusion-afx如何化繁为简。
传统Fusion代码(示例):
prototype(Vendor.Site:Example) < prototype(Neos.Fusion:Component) {
title = 'title text'
subtitle = 'subtitle line'
imageUri = 'https://dummyimage.com/600x400/000/fff'
renderer = Neos.Fusion:Tag {
tagName = 'div'
content = Neos.Fusion:Join {
headline = Neos.Fusion:Tag {
tagName = 'h1'
content = ${props.title}
attributes.class = 'headline'
}
subheadline = Neos.Fusion:Tag {
tagName = 'h2'
content = ${props.subtitle}
attributes.class = 'subheadline'
@if.hasSubtitle = ${props.subtitle ? true : false}
}
image = Vendor.Site:Image {
uri = ${props.imageUri}
}
}
}
}这段代码虽然功能完整,但其冗长的结构和大量的Neos.Fusion:Tag、Neos.Fusion:Join让人难以快速理解组件的HTML结构。
使用neos/fusion-afx重构后:
prototype(Vendor.Site:Example) < prototype(Neos.Fusion:Component) {
title = 'title text'
subtitle = 'subtitle line'
imageUri = 'https://dummyimage.com/600x400/000/fff'
renderer = afx`
{props.title}
{props.subtitle}
`
}是不是瞬间感觉清爽了许多?通过afx反引号包裹的代码块,我们用类似HTML/JSX的语法直接定义了组件的渲染结构。neos/fusion-afx会在后台将其解析并转换为与传统Fusion代码等价的结构。
AFX 的核心语法规则
AFX语法非常直观,但也有一些值得注意的规则:
-
HTML标签:
会被转换为HelloNeos.Fusion:Tag对象。所有属性都会作为标签属性渲染。 -
Fusion对象标签:
会被解释为对Vendor.Site:MyComponent原型的引用,所有属性都将作为顶级Fusion属性传递。 -
Eel表达式:使用花括号
{}包裹的表达式,如{props.title},会被解析为Eel表达式。 -
Spread语法:支持类似ES6的Spread语法
{...expression},可以将一个Fusion数据结构的所有属性应用到当前原型上。这对于动态传递大量属性非常有用(需要Neos >= 4.2)。会被转换为一系列
@apply语句,实现属性的合并和覆盖。 -
子节点处理:
- 如果AFX标签只有一个子节点,它会直接渲染到父节点的
content属性。 - 如果AFX标签有多个子节点,它们会被渲染为
Neos.Fusion:Join对象,并作为父节点的content。 - 可以使用
@key属性为子节点指定Fusion属性名,否则会使用item_1,item_2等默认索引。 -
@path属性允许你将子节点渲染到父节点指定路径下的Fusion属性,而不是默认的content。
- 如果AFX标签只有一个子节点,它会直接渲染到父节点的
-
Meta属性:以
@开头的属性,如@if.hasSubtitle,会被直接添加到生成的Fusion原型上,用于条件渲染、处理流程等。 - 空白和换行:AFX对空白字符的处理进行了优化,例如文本字面量中的多行空白会折叠为单个空格,而与换行符相连的空白通常会被忽略,以保持代码简洁。
实际应用示例
AFX的强大之处在于它能与现有的Fusion机制无缝结合。
1. 渲染集合 (Neos.Fusion:Collection)
当你需要迭代渲染列表项时,AFX与Neos.Fusion:Collection的结合非常优雅:
prototype(Vendor.Site:IterationExample) < prototype(Neos.Fusion:Component) {
items = null // 例如: array {[href:'...', title:'...'], ...}
renderer = afx`
这里,@path='itemRenderer' 将元素渲染到Neos.Fusion:Collection的itemRenderer属性中,而不是默认的content,使得结构更加清晰。
2. 增强子组件 (Neos.Fusion:Augmenter)
Neos.Fusion:Augmenter允许你在不修改子组件API的情况下,为其添加额外的属性。AFX让这种模式变得更加直观:
prototype(PackageFactory.AtomicFusion.AFX:SliderExample) < prototype(Packagefactory.AtomicFusion:Component) {
images = ${[]}
renderer = afx`
`
}在这个例子中,Neos.Fusion:Augmenter为每个Vendor.Site:ImageExample实例动态添加了class="slider__slide"和data-index属性,而ImageExample原型本身无需感知这些外部的修改。
总结与优势
neos/fusion-afx 是Neos开发者工具箱中一个不可多得的利器。它的核心优势在于:
- 代码简洁性与可读性:极大地减少了Fusion代码的冗余,使其更接近传统HTML模板,便于快速理解和维护。
- 组件化开发体验:提供了更接近前端框架(如React)的组件编写体验,让开发者能更专注于组件的结构和逻辑。
- 无需额外模板文件:将视图逻辑直接集成到Fusion文件中,简化了项目结构。
- 强大的可扩展性:由于最终生成的是标准Fusion代码,你可以继续利用Fusion的强大功能进行扩展和重写。
- 提升开发效率:减少了样板代码的编写,加快了组件的开发速度。
如果你也曾为冗长的Fusion代码而烦恼,那么我强烈推荐你尝试一下neos/fusion-afx。它不仅能让你的代码更优雅、更易读,还能显著提升你的开发体验和效率,让你在Neos开发中如虎添翼!










