packagefactory / atomicfusion-afx
Requires
- neos/fusion: ^3.2.0 || ^4.0.0 || dev-master
- packagefactory/afx: ~2.0.1
Requires (Dev)
- phpunit/phpunit: ~4.8 || ~5.4.0
README
该包已弃用,推荐使用 https://github.com/neos/fusion-afx。此包将继续可用于依赖它的现有设置,但不会添加错误修复或新功能。
Neos.Fusion 的 JSX 启发式紧凑语法
该包提供了一种融合预处理器,可以将紧凑的 xml 风格语法扩展为纯融合代码。这允许编写紧凑的组件,无需单独的模板文件,并使定义的原型具有计划外的可扩展性,因为生成的融合代码可以在需要时被覆盖和控制。
安装
PackageFactory.AtomicFusion.AFX 通过 Packagist 提供。只需将 "packagefactory/atomicfusion-afx" : "~3.0.0"
添加到 composer.json 的 require 部分,或运行 composer require packagefactory/atomicfusion-afx
。
我们使用语义版本控制,每次重大更改都会增加主版本号。
使用
使用此包,以下融合代码
prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
title = 'title text'
subtitle = 'subtitle line'
imageUri = 'https://dummyimage.com/600x400/000/fff'
#
# The code afx`...` is converted to the fusion code below at parse time.
# Attention: Currently there is no way to escape closing-backticks inside the Expression.
#
renderer = afx`
<div>
<h1 @key="headline" class="headline">{props.title}</h1>
<h2 @key="subheadline" class="subheadline" @if.hasSubtitle={props.subtitle ? true : false}>{props.subtitle}</h2>
<PackageFactory.AtomicFusion.AFX:Image @key="image" uri={props.imageUri} />
</div>
`
}
将被转换,解析并缓存,然后评估为等价于以下融合代码
prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
title = 'title text'
subtitle = 'subtitle line'
imageUri = 'https://dummyimage.com/600x400/000/fff'
renderer = Neos.Fusion:Tag {
tagName = 'div'
content = Neos.Fusion:Array {
headline = Neos.Fusion:Tag {
tagName = 'h1'
content = ${props.title}
attributes.class = 'headline'
}
subheadline = Neos.Fusion:Tag {
tagName = 'h2'
content = ${props.subtitle}
attributes.subheadline = 'subheadline'
@if.hasSubtitle = ${props.subtitle ? true : false}
}
image = PackageFactory.AtomicFusion.AFX:Image {
uri = ${props.imageUri}
}
}
}
}
AFX 语言规则
忽略外部元素周围的全部空白。与换行符相连的空白被视为无关紧要并忽略。
HTML 标签(无命名空间标签)
HTML 标签被转换为 Neos.Fusion:Tag
对象。afx 标签的所有属性都作为标签属性渲染。
以下 HTML
<h1 class="headline" @if.hasHeadline={props.headline ? true : false}>{props.headline}</h1>
被转换成
Neos.Fusion:Tag {
tagName = 'h1'
attributes.class = 'headline'
content = ${props.headline}
@if.hasHeadline = ${props.headline ? true : false}
}
如果标签是自闭合且没有内容,它将被渲染为自闭合融合标签。
<br/>
被转换成
Neos.Fusion:Tag {
tagName = 'br'
selfClosingTag = true
}
融合对象标签(命名空间标签)
所有命名空间标签都被解释为原型名称,所有属性都作为顶级融合属性传递。
以下 HTML
<Vendor.Site:Prototype type="headline" @if.hasHeadline={props.headline ? true : false}>{props.headline}</Vendor.Site:Prototype>
被转换成
Vendor.Site:Prototype {
type = 'headline'
content = ${props.headline}
@if.hasHeadline= ${props.headline ? true : false}
}
标签子元素
afx 节点下子节点的处理方式根据找到的 childNodes 的数量而不同。
单个标签子元素
如果 AFX 标签恰好包含一个子元素,则该子元素将直接渲染到 content
属性中。
子元素随后被解释为字符串、eel 表达式、html 或融合对象标签。
以下 AFX 代码
<h1>{props.title}</h1>
被转换成
Neos.Fusion:Tag {
tagName = 'h1'
content = {props.title}
}
多个标签子元素
如果 AFX 标签包含多个子元素,则内容将被渲染为 Neos.Fusion:Array
并放入 content
属性中。子元素被解释为字符串、eel 表达式、html 或融合对象标签。
以下 AFX 代码
<h1>{props.title}: {props.subtitle}</h1>
被转换成
Neos.Fusion:Tag {
tagName = 'h1'
content = Neos.Fusion:Array {
item_1 = {props.title}
item_2 = ': '
item_3 = ${props.subtitle}
}
}
标签子元素内的@key
属性用于更改融合属性的名称,以便将数组子元素渲染进去。如果没有提供@key
属性,则从x=1
开始使用index_x
。
<Vendor.Site:Prototype @children="text">
<h2 @key="title">{props.title}</h1>
<p @key="description">{props.description}</p>
</Vendor.Site:Prototype>
被转换成
Vendor.Site:Prototype {
text = Neos.Fusion:Array {
title = Neos.Fusion:Tag {
tagName = 'h2'
content = ${props.title}
}
description = Neos.Fusion:Tag {
tagName = 'p'
content = ${props.description}
}
}
}
元属性
一般来说,所有元属性都是以@符号开头的。
@children
属性定义了用于将当前标签的内容/子元素渲染进去的属性。子元素的默认属性名为content
。
@key
属性可用于在渲染数组时定义其兄弟元素中某项的属性名。如果没有定义@key
,则从`x=1`开始使用index_x
。
所有其他元属性都直接添加到生成的原型中,并可用于@if或@process语句。
空白符和换行符
Afx不是HTML,对代码进行了一些简化以优化生成的融合,并允许以结构化方式表示组件层次结构。
以下规则被应用
- 与换行符相连的新行和空白字符被视为无关紧要,并被忽略
<h1>
{'eelExpression 1'}
{'eelExpression 2'}
</h1>
被转换成
Neos.Fusion:Tag {
tagName = 'h1'
contents = Neos.Fusion:Array {
item_1 = ${'eelExpression 1'}
item_2 = ${'eelExpression 2'}
}
}
- 单行元素之间的空格被视为有意义的,并被保留
<h1>
{'eelExpression 1'} {'eelExpression 2'}
</h1>
被转换成
Neos.Fusion:Tag {
tagName = 'h1'
contents = Neos.Fusion:Array {
item_1 = ${'eelExpression 1'}
item_2 = ' '
item_3 = ${'eelExpression 2'}
}
}
示例
使用Neos.Fusion:Collection
渲染集合
为了渲染列表或菜单,表示组件通常将预处理的数组数据作为prop接收。要在afx中迭代此类数组,可以使用Neos.Fusion:Collection
。
prototype(PackageFactory.AtomicFusion.AFX:IterationExample) < prototype(PackageFactory.AtomicFusion:Component) {
# array {[href:'http://www.example_1.com', title:'Title 1'], [href:'http://example_2.com', title:'Title 2']}
items = null
renderer = afx`
<ul @if.has={props.items ? true : false}>
<Neos.Fusion:Collection collection={props.items} itemName="item" @children="itemRenderer">
<li><a href={item.href}>{item.title}</a></li>
</Neos.Fusion:Collection>
</ul>
`
}
使用PackageFactory.AtomicFusion:Augmenter
增强子组件
可以使用PackageFactory.AtomicFusion:Augmenter
来向渲染的内容添加额外的属性。这允许在不扩展组件API的情况下提供一些渲染灵活性。这是一个有用的模式,在只需要额外类的情况下,可以避免不必要的标签包装。
prototype(PackageFactory.AtomicFusion.AFX:SliderExample) < prototype(Packagefactory.AtomicFusion:Component) {
images = ${[]}
renderer = afx`
<div class="slider">
<Neos.Fusion:Collection collection={props.images} itemName="image" iterationName="iteration" @children="itemRenderer">
<PackageFactory.AtomicFusion:Augmenter class="slider__slide" data-index={iteration.index}>
<PackageFactory.AtomicFusion.AFX:ImageExample image={image} />
</PackageFactory.AtomicFusion:Augmenter>
</Neos.Fusion:Collection>
</div>
`
}
该示例遍历一张图片列表,并使用PackageFactory.AtomicFusion.AFX:ImageExample
渲染每一张图片,同时PackageFactory.AtomicFusion:Augmenter
添加来自外部的类和数据属性。