Ставится задача сделать интерфейс. Интерфейс разбивается функциональные блоки. Допустим блок - компонент. Далее все учатсники процесса обсуждают фичлист этого болка на основе ТЗ, с учетом UX. После этого имеем нечто такое component.json
{
"type": "component",
"name": "Product Card",
"description": "Карточка продукта. Представление базовой информации о продукте и основных действий с ним",
"features": {
"cover": {
"type": "Image",
"description": "Фото продукта"
},
"description":{
"type": "Text",
"description": "Краткое описание"
},
"price":{
"type": "String",
"description": "Цена"
},
"addToFav":{
"type": "Action",
"description": "Добавить в избранное(корзина)",
"default": false
},
"removeFromFav": {
"type": "Action",
"description": "Удрать из избранного(корзина)",
"default": false
},
"requestPrice": {
"type": "Action",
"description": "Если у товара не указана цена - её можно узнать через обратную связь",
"default": false
},
"orderProduct": {
"type": "Action",
"description": "Быстрый заказ товара",
"default": false
},
"showProductInfo":{
"type": "Action",
"description": "Перейти к товару"
}
}
}
Эта часть какбы не далее не обсуждается. Далее совсем небольшая магия на основе описания выше. Все описаные ключевые элементы теперь доступны нам в этой папочке автоматически.
есть 2 файлика для верстальщика. Стили и представление. В целом дальше мне пофигу что он там наверсает. Главное что бы присутствовали все элементы из описания. Верстальшик же не думает ни о какой логике и состоянии. layout.jsx
/** @jsx elements */
import styles from './styles.styl'
export default function (elements) {
const {
Root,
Cover,
Price,
Description,
AddToFavButton,
RequestPrice,
RemoveFromFavButton,
OrderProductButton
} = elements
return (
<Root className={styles.root}>
<Cover className={styles.cover} src="dumb.jpg" alt=""/>
<Price className={styles.price}>
50 000 руб.
<RequestPrice className={styles.requestPrice}>Узнать цену</RequestPrice>
</Price>
<hr className={styles.hr} ref="hr"/>
<Description className={styles.description}>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia dolor eaque quia porro suscipit hic a consequuntur qui!</Description>
<div className={styles.actions} ref="actions">
<AddToFavButton className={styles.addToFav}>Добавить в список</AddToFavButton>
<RemoveFromFavButton className={styles.removeFromFav}>Убрать из списка</RemoveFromFavButton>
<OrderProductButton className={styles.orderProduct}>Заказать изделие</OrderProductButton>
</div>
</Root>
)
}
и есть файлик с логикой. В инстансе которого также доступны все ключевые элементы. Тут же можно задавать депендеси.
export default class {
...
@prop('cover:string')
@prop('article:string.required')
cover (element, ...props) {
const { cover, article } = props
let src, className, alt
if (cover) {
src = cover
alt = `${article} cover`
} else {
src = '/cdn/no-photo.jpg'
alt = `${article}`
element.className + ' ' + styles.noPhoto
}
return element({ src, className, alt })
}
...
}
Главное, что это файлик можно многократно экстендить и разделять на любые уровни. Типа - логика данных, логика состояния, анимации и что угодно.
Например анимировать.
...
animations () {
return {
fadeIn {
duration: 300,
},
hover {
duration: 1000,
}
}
}
@animation('fadeIn')
@action('opacity', [0,1])
root (style, element) {
return element({ style })
}
@animation('hover')
@action('top', ['50px','0px'], [0, 40])
@action('opacity', [0.8,1], [20, 60])
cover (style, element) {
return element({ style })
}
...