bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

jsx и bemjson #1084

Closed vitkarpov closed 8 years ago

vitkarpov commented 8 years ago

Коллеги!

Для описания БЭМ-дерева мы используем bemjson (или bemtree, который позволяет создавать полный bemjson страницы по частям, что по сути — то же самое, верно?) Однако, по своей природе json — довольно многословный формат представления данных, а html (jsx) более лаконичный.

Есть какие-то трансляторы jsx -> bemjson? Наверняка, кто-то думал в эту сторону, имеет ли это практичный смысл?

tadatuta commented 8 years ago

https://www.npmjs.com/package/html2bemjson

vitkarpov commented 8 years ago

Это про чистый HTML. Я скорее про:

<Popup js={{ "foo": this.ctx.foo }}>
  <MyBlock title="Hello, world!" />
</Popup>
tadatuta commented 8 years ago
require('html2bemjson').convert(`
<Popup js={{ "foo": this.ctx.foo }}>
  <MyBlock title="Hello, world!" />
</Popup>
`);
/*
{ tag: 'popup',
  attrs: { js: '{{', '"foo":': '', 'this.ctx.foo': '', '}}': '' },
  content: { tag: 'myblock', attrs: { title: 'Hello, world!' } } }
*/

Насколько я понимаю, нужно лишь добавить поддержу {{}} в атрибутах?

vitkarpov commented 8 years ago

Это да, но не только. В данном примере должен получиться:

({
  block: 'popup',
  js: { 'foo': ... },
  content: {
    block: 'my-block',
    title: 'Hello, world!' 
  }
})

Т.е. идея в том, чтобы описывать именно БЭМ-дерево, а не HTML, более лаконично.

vitkarpov commented 8 years ago

Под капотом, шаблонизатор все равно будет работать с bemjson, а человек — с jsx

vitkarpov commented 8 years ago

Я почему про это подумал (не только я, идея очевидная). Кажется, что компонентный подход стал популярнее в последнее время, с распространением реакта, во многом благодаря тому, что дерево компонентов описывается, условно в привычном для многих XML (HTML), нет?

tadatuta commented 8 years ago

Если это правда кто-то будет использовать, то сделать можно, дело не хитрое. Но что-то есть у меня сомнения.

Если запилю, вы действительно будете использовать у себя на проектах?

vitkarpov commented 8 years ago

Пока это просто вброс — интересно, что народ думает

vitkarpov commented 8 years ago

Мне кажется, что для ребят, которые привыкли «верстать статичный HTML», а так же для тех, у кого «реакт головного мозга», такой интерфейс будет привычнее — соответственно, порог вхождения уменьшится (просто мысли, не факт)

qfox commented 8 years ago

Мне кажется, что для ребят, которые привыкли «верстать статичный HTML», а так же для тех, у кого «реакт головного мозга», такой интерфейс будет привычнее

Да, но порог это врядли уменьшит, и, вероятно, будет больше путаницы. Но минусов в том, чтобы уметь собирать из bundle.bem.xml вместо bundle.bemjson.js, я не вижу ;-).

vitkarpov commented 8 years ago

Но минусов в том, чтобы уметь собирать из bundle.bem.xml вместо bundle.bemjson.js, я не вижу ;-).

Лишь бы толк был, а не «еще один стандарт», как в известном меме :)

awinogradov commented 8 years ago

@vitkarpov это невозможно. Можно только конвертировать bemjson в jsx. Обратно без дополнительных знаний не получится, потому что на одном уровне jsx находится несколько уровней bemjson. Например, не существует возможности отличить value в jsx от { block: 'b', value: value }, { block: 'b', attrs: {value: value} }, { block: 'b', mods: {value: value} }, { block: 'b', mix: {block: 'b2', value: value} }. Самое важное во всем этом, что правила конвертации для каждого блока уникальны.

awinogradov commented 8 years ago

Это касается безусловно плоской записи. Если есть желание писать примерно так:

<BEM block='b1' mods={{ mod1: 'val1' }} attrs={{ value: 'val' }} mix={{}}>content</BEM>

То сделать действительно легко, как и сказал @tadatuta, но кажется в этом нет смысла. Ибо в реальном коде это превратится в:

<BEM 
    block='b1' 
    mods={{ mod1: 'val1' }} 
    attrs={{ value: 'val' }} 
    mix={{}}>
        content
</BEM>
vitkarpov commented 8 years ago

@awinogradov это да — придется вводить дополнительные соглашения, например, введя пространство имен для зарезервированных атрибутов:

<Popup bemMix="..." bemMods="..." bemJs="...">

ну или запретить использовать эти атрибуты в качестве кастомных, для АПИ своего компонента :)

Я уверен, что найдутся и другие неоднозначные моменты.

awinogradov commented 8 years ago

@vitkarpov я могу рассказать как мы решаем это в Лего)

vitkarpov commented 8 years ago

«это» — что именно? :) Упрощаете синтаксис bemjson?

awinogradov commented 8 years ago

Реализуем интерфейс на jsx в React для бэм-компонентов.

vitkarpov commented 8 years ago

Это история про jsx-адаптер?

awinogradov commented 8 years ago

Я не знаю что это такое) Но история есть и длинная)

vitkarpov commented 8 years ago

Ну, я имею ввиду, что можно писать jsx, вместо bemjson, который, под капотом, bemhtml умеет понимать в рантайме?

vitkarpov commented 8 years ago

Если это другая история — конечно, интересно послушать :) Если это укладывается в рамки форума, конечно.

awinogradov commented 8 years ago

можно писать jsx, вместо bemjson, который, под капотом, bemhtml умеет понимать в рантайме?

Именно так ;)

Если это другая история...

Почему другая если проблема одна?)

vitkarpov commented 8 years ago

Не, задача та же, я про то, что эту историю я знаю. Нормальный ход! Согласен с тем, что компилировать, возможно, смысла и нет, если можно научить шаблонизатор понимать другой формат описания входных данных.

А есть в этом реальная польза, в смысле, все радостно начинают писать xml вместо bemjson?

awinogradov commented 8 years ago

Нет, но мы решили инкапсулировать весь многогранный мир БЭМ за простым API в jsx для React-пользователей. Условно мы живем в чужом стеке по его правилам, что дает понимание как работать с компонентами разработчикам, которые уже знакомы с React. Кроме того такая инкапсуляция позволяет защитить разработчика от разного рода фривольностей. При таком подходе он может модифицировать компонент только так как это позволяет пропсы. Влезть внутрь и поменять bemjson он не может.

vitkarpov commented 8 years ago

в jsx для React-пользователей

Ммм, кажется, я не совсем понимаю — надо уточнить. А если нет Реакта?

Условно, я фрилансер, и хочу сверстать простой лендинг на БЭМ. Хочу побить всю страничку на компоненты, продумать их АПИ, далее описать страничку в xml (как в старые добрые времена), и получить HTML в браузер — не важно, статичную верстку один раз, или накладывать шаблоны на сервере в рантайме.

Мне не нужно, что бы jsx компилировался в React.createElement и все такое.

vitkarpov commented 8 years ago

Кроме того такая инкапсуляция позволяет защитить разработчика от разного рода фривольностей.

А всякие миксы и мода js?

awinogradov commented 8 years ago

А всякие миксы и мода js?

Миксы деградировали до нативного className. js мода отвалилась, ибо нужна только для i-bem.

Мне не нужно, что бы jsx компилировался в React.createElement и все такое.

Мы превращаем jsx в bemjson. Так как bem-xjst понимает именного его. Мы обрабатываем результат выполнения React.createElement.

awinogradov commented 8 years ago

Мне не нужно, что бы jsx компилировался в React.createElement и все такое.

Это невозможно) Вернее как, если кастомно по-своему реализовать компиляцию, то можно и машку. По одной простой причине: jsx нужен чтобы коротко описывать React.createElement.

<div className='test'>text</div>

Компилируется в:

React.createElement('div', { className: 'test' }, 'text');
vitkarpov commented 8 years ago

Мы превращаем jsx в bemjson. Так как bem-xjst понимает именного его. jsx нужен чтобы коротко описывать React.createElement

Что-то не совсем пойму, давай попробую сформулировать, а ты меня поправишь.

Есть такой bemjson:

({
  block: 'popup',
  content: [{
    block: 'button',
    text: 'Hello, world!'
  }]
})

сейчас это дело принимает шаблонизатор и выдает html.

Хочется:

<Popup>
  <Button text="Hello, world!" />
</Popup>

по-прежнему, это дело принимает шаблонизатор и выдает html.

Если jsx компилирует в React.createElement, то и рендерить это дело должен реакт — при чем здесь bemhtml?

vitkarpov commented 8 years ago

Если jsx компилирует в React.createElement, то и рендерить это дело должен реакт — при чем здесь bemhtml

Т.е. задача не в том, чтобы по bemhtml-шаблонам получить jsx и скормить его реакту (это задача про «научить реакт понимать bemhtml»), а в том, чтобы позволить человеку писать jsx вместо bemjson.

Что я упускаю?

vitkarpov commented 8 years ago

jsx нужен чтобы коротко описывать React.createElement

Наверное, лучше вообще абстрагироваться от jsx и говорить xml :)

Yeti-or commented 8 years ago
({
  block: 'popup',
  theme: 'action',
  mods: {'action': 'action'},
  action: {text: 'install me now'},
  content: {
    block: 'button',
    mix: {block: 'popup', elem: 'button', mods: {'action': 'yes'}},
    attrs: {name: 'id-4'},
    name: 'Hello, world!', 
    text: 'Hello, world!'
  }
})
tadatuta commented 8 years ago

Наверное, лучше вообще абстрагироваться от jsx и говорить xml

Примерно лет 6 назад в Лего появился скрипт, превращающий XML в BEMJSON ;)

qfox commented 8 years ago

@tadatuta Вот. Практика показывает, что это плохой путь! Ну или не практика. И не показывает. И не такой уж плохой.

Yeti-or commented 8 years ago

да всё просто по кругу идёт 🌀

Yeti-or commented 8 years ago

@vitkarpov можешь мой bemjson перевести в jsx?

Yeti-or commented 8 years ago

я не набрасываю если что

vitkarpov commented 8 years ago

Примерно лет 6 назад в Лего появился скрипт, превращающий XML в BEMJSON ;)

@tadatuta а почему это произошло? Насколько я понял, потому что умирал xslt и все переписывалось на JavaScript, а какой родной формат представления данных в JavaScript — json. Т.е. сам по себе xml не плох, а именно в сочетании с xslt-шаблонами, верно?

vitkarpov commented 8 years ago

@Yeti-or ты к тому, что в значениях многих атрибутов json и не очень ясно как это вытянуть в плоский список атрибутов?

tadatuta commented 8 years ago

@vitkarpov нууу, не знаю... сам по себе XML, конечно, неплох, но возможность в BEMJSON сделать [].map() и прочие JS-штуки — это приятно :)

vitkarpov commented 8 years ago

сделать [].map() и прочие JS-штуки

Ну, с jsx это как раз можно сделать:

{this.ctx.users.map(user => {
  return <User name={user.name} />;
})}

лучшее из обоих миров :)

vitkarpov commented 8 years ago

Спасибо всем за обратную связь, в целом, я понял что и как 👍