Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #41 (permalink)  
Старый 28.02.2015, 20:58
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от l-liava-l
Википедия:
Цитата:
Шаблонизатор (в web) — это программное обеспечение, позволяющее использовать html-шаблоны для генерации конечных html-страниц.
Реакт предназначен именно для этого, а его возможности, недостатки и архитектура не имеют значения в данном случае.
Оно не конечный html страниц, оно виртуальный DOM, который рендерится в HTML. Оно не HTML, оно имеет XML ситнаксис, как минимум и оно имеет свой шаблонизатор.

Сообщение от l-liava-l
Ангуляр это целая система в которой тож есть свой шаблонизатор.
Это лицемерие. У реакта тоже есть шаблонизатор и называется он тадам JSX, а ещё есть архитектурное решение ака flux, а ещё есть аддоны, которые тоже часть системы. Не хочешь не подключай, ну дык я думаю в ангуляре также.

Будь здоров, кушай торт, он полезен
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #42 (permalink)  
Старый 07.03.2015, 17:37
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Есть две архитектуры flux(store, action, component, dispatcher). Одна зависима от другой. Это значит что пока 1 не обновиться, 2 не должен обновляться.
Как организовать внутри одного диспетчера я понимаю(ставим waitFor), а между двумя как построить взаимосвязь недогоняю.

Как организовать эту зависимость с диспетчерами?
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #43 (permalink)  
Старый 07.03.2015, 19:11
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Gozar Посмотреть сообщение
Есть две архитектуры flux(store, action, component, dispatcher). Одна зависима от другой. Это значит что пока 1 не обновиться, 2 не должен обновляться.
Как организовать внутри одного диспетчера я понимаю(ставим waitFor), а между двумя как построить взаимосвязь недогоняю.

Как организовать эту зависимость с диспетчерами?
Добро пожаловать на грабли событийного программирования! С моделями было проще, да?)

Flux должен быть один. Dispatcher - тоже. http://fluxxor.com/images/flux-complex.png

Хочу заметить, я перепробовал все способы и остановился на одном, как самом удобном. Он выделен красным. Почему он - расскажу в конце.

1. Асинхронные действия. Из action возвращаешь Promise. Когда он выполнится, выполняешь другое действие
2. waitFor. Это, можно сказать, сахар над Store.on('change'). Все просто - в хранилище A выполняешь waitFor('B', callback). Когда вызовится B.emit('change'), выполнится и переданный callback
3. Недокументированный API. Хранилища наследуются от EventEmitter. У него есть привычный всем метод once (колбек на один раз).
4. componentDidUpdate(prevProps, prevState) внутри Controller Component. Проверяем, изменились ли данные в новом состоянии. Если да - отсылаем action.

Теперь обо всём по порядку.

1. Асинхронные действия

добавляем в actions параметр callback, или возвращаем Promise.

Это идет в разрез с идеей Flux. Это не стоит использовать (имхо)

2. waitFor

waitFor мне неплохо вмазал (шо аж день не отпускало), так что, думаю, следует хорошо пояснить этот момент

Я использовал Fluxxor, так что его и буду описывать. Документация по Store.waitFor

Как вы видите, waitFor должен находиться внутри хранилища. Как тогда выполнить обновление с зависимостями?

A - master Store
B - slave Store


Сналача, регистрируем обработчик изменения через вызов нужного action (напр. Flux.actions.b.waitForAUpdate)
Далее, выполняем изменение хранилища A (напр. Flux.actions.a.setItem)

И приходим к проблеме. Вызов этого дела выглядит так:
Flux.actions.b.waitForAUpdate()
Flux.actions.a.setItem('yolo')


А проблема в том, что идеология Flux не разрешает отправлять больше одного действия одновременно (а они не обязательно синхронные -т.е. нельзя рассчитывать на это, и нужно надавить на реактивность)

тут либо можно изгальнутся костылем, пустив обновление состояния A через таймаут:
Flux.actions.b.waitForAUpdate()
setTimeout( () => Flux.actions.a.setItem('yolo') )


либо вернуть из создателя действия (ActionCreator, лол) обещание, которое содержит в себе таймаут:
Flux.actions.b.waitForAUpdate().then( () =>
  Flux.actions.a.setItem('yolo')
)


Исходник для Flux.actions.b.waitForAUpdate получается таким:

Файл flux/actions/b.js:
export default {
  waitForAUpdate() {
    return Promise.delay().then(() => 
      this.dispatch('WAIT_FOR_A_STORE')
    )
  },
}

(Promise.delay - это нестандартный метод, из библиотеки bluebird)

Для сравнения, создатель действия без обещания - такой:
Файл flux/actions/b.js:
export default {
  waitForAUpdate() {
    this.dispatch('WAIT_FOR_A_STORE')
    // и чё, кода действие выполнится то?
  },
}


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

3. Недокументированный API.

У нас ведь Flux, так? значит, все действия и хранилища видны всему.

Вкратце - одноразово подписываемся на событие изменения, и из него уже дальше пляшем
Flux.stores('A').once('change', () => {
  // хранилище изменило состояние
  const AState = Flux.stores('A').getState()
  Flux.actions.b.doSimethingWith(AState)
})

Flux.actions.a.setItem('yolo')


Наверное, это дело лучше красиво спрятать в ActionCreator, обернув обещанием.

4. componentDidUpdate(prevProps, prevState)

Имхо, кажется костыльным и уродивым, но это похоже на самый хороший и добротный способ, с точки зрения асинхронной реактивности (имхо)

Состояние хранилищ передается controller component, который расфасовывает полученные данные вниз по дереву компонентов через свойства (props)

Fluxxor предоставляет сахарок для легкого подписывания на событие изменения хранилищ и перевод их состояний в состояние компонента.

componentDidUpdate, как вы знаете, вызывается после того, как у компонента сменились свойства или состояние. Ну и измениться они могут, в случае controller component, из-за смены состояния одного из прослушиваемых хранилищ

выглядит это так:

A - master Store
B - slave Store


Пусть компонент копирует состояния хранилищ в пространства имен :
// это - слушалка события 'change' у двух наших хранилищ
onSomeStoreChanged() {
  const A = Flux.stores('A').getState()
  const B = Flux.stores('B').getState()

  return { A, B }
}

// состояние хранилища A будет в this.state.A
// для B  - соотв.


отсылаем данные хранилищу A:
Flux.actions.A.setItem('yolo')


внутри CDU, если что-то изменилось, и это состояние хранилища А, то нужно обновить данные в В:
componentDidUpdate(prevProps, prevState) {
  if (this.state.A !== prevState.A) {
    Flux.actions.b.updateFromItem(this.state.A.item)
  }
}


ну, или можно использовать CWU (цепочка реакций должна пойти быстрее):
componentWillUpdate(nextProps, nextState) {
  if (this.state.A !== nextState.A) {
    Flux.actions.b.updateFromItem(nextState.A.item)
  }
}


А у нас цепочка зависимостей (A -> B -> C)? Тогда:
componentWillUpdate(nextProps, nextState) {
  if (this.state.A !== nextState.A) {
    Flux.actions.b.updateFromItem(nextState.A.item)
  }
  if (this.state.B !== nextState.B) {
    Flux.actions.c.updateFromItem(nextState.B.item)
  }
}


Как-то так ... в общем, у нас есть перенос логики обновления в компоненты-контроллеры, но для Flux - это нормально (вроде)

Почему лучше использовать CWU/CDU для цепочки событий? Все просто - действие (action), на момент выполнения этих методов, уже прошло круг от создателя действий до компонентов (напомню, только одно действие может обходить кружок в момент времени).

waitFor обеспечивает такой же функционал (вызывается, когда хранилище заявило об изменении состояния), но как вызвать действие (Action) внутри хранилища (Store)? МБ дело вкуса, но я лучше не буду пихать всякие actions.yolo() внутри чистенького Store.

Ну и еще - разделение логики обновления данных от самого обновления данных

И еще - абстрагирование от того, сколько действие выполняется. Получается действительно реактивная система обмена данными

Всё вышесказанное является огромнейшим ИМХО. Если есть предложения, буду рад их услышать.

Последний раз редактировалось melky, 07.03.2015 в 19:35.
Ответить с цитированием
  #44 (permalink)  
Старый 07.03.2015, 19:45
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Ещё пометочка, но отдельным сообщением.

1. Для сравнений типа this.state.B !== nextState.B нужно, чтобы данные не были мутабельными (иммутабельность, короче)

Это делается либо через _.cloneDeep, либо использованием билиотек, предоставляющих иммутабельные структуры данных

Можно и проверять на предмет изменения объекта через _.isEqual(this.state.B, nextState.B), но спор иммутабельность vs мутабельность - отдельная тема

2. Controller component - шаблон проектирования компонентов. Заключается в том, чтобы выделить 2 компонента, которые по одиночке используют один Store и поставить над ними родителя, который содержит в себе получение данных из Flux и её передачу по дереву компонентов с помощью props.

что-то типа такого (но тут не один Store, а два): http://2.bp.blogspot.com/-mSMHB7w43l...30.05%2BPM.png

count_control и sold_flag_control берется из Flux и передается компонентам через props с именами Sold flag и Count
Ответить с цитированием
  #45 (permalink)  
Старый 11.03.2015, 12:57
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

React v0.13
Ответить с цитированием
  #46 (permalink)  
Старый 11.03.2015, 15:24
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от melky
React v0.13
Не пинали бы меня со сроками запуска, начал бы переезд
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #47 (permalink)  
Старый 20.04.2015, 23:03
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Накой было резать html autocomplete?
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #48 (permalink)  
Старый 01.05.2015, 22:36
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Поскольку ангуляр достал своим DI, тормозами и прочим, решил ознакомиться с реактом. Вчера посмотрел видео, сегодня почитал доку и написал первый пример на es6 + React.
//Test.jsx

class Test extends React.Component {

    render() {
        return (
            <h1>test</h1>
        );
    }

}

export default Test;

//client.js

import Test from './components/Test.jsx';

React.constructAndRenderComponent(
    Test,
    {},
    document.getElementById('container')
);

<!DOCTYPE html>
<html>
<head>
    <title>React Sandbox</title>
    <meta charset="utf-8">
    <script src="lib/react.js"></script>
</head>
<body>
    <div id="container"></div>
    <script src="dist/sandbox.js"></script>
</body>
</html>


результат https://yadi.sk/i/hrZgXP64gNiUf

С документацией по 0.13.2, конечно, беда.

Хочется, как в шаблонизаторе лепить ифы и фор_ичи, но нельзя
Как же быть?
Смотрел в сторону react-templates, но не уверен.

Сообщение от l-liava-l
Ангуляр это целая система в которой тож есть свой шаблонизатор.
спрашивается, на кой такая система сдалась:
1. DI ангуляра не нужен, т.к. есть es6 модули
2. утилиты (forEach, isObject, etc) мне тоже не сдались, у меня свои
3. транспорт ангуляра (ajax) не требуется, у меня свой
Т.о., если модели у меня свои, утилиты свои, свой транспорт, но ангуляр заставляет меня юзать его собственные и при этом тормозит... не хорошо это
Да, с ним можно писать меньше кода. Декларативность нравится, но стоит ли оно того?
По большому счету, теперь мне нужна только вьюха.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук

Последний раз редактировалось nerv_, 01.05.2015 в 22:47.
Ответить с цитированием
  #49 (permalink)  
Старый 01.05.2015, 23:19
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от nerv_
С документацией по 0.13.2, конечно, беда.
Там минимальные отличия от 0.12. Читай 0.12, отличия сами дойдут.

Сообщение от nerv_
посмотрел видео
Это видео, ещё та жесть. Смотри видео вконтактике в группе https://vk.com/reactjs и на eggheads


Сообщение от nerv_
Хочется, как в шаблонизаторе лепить ифы и фор_ичи, но нельзя
Как же быть?
Почему нельзя? Ещё как можно и нужно
Там сборка идет в рендере перед return

render: function () {
        var i = 0;
        var imgs = this.props.list.length == 0 ? '' : this.props.list.map(function(item){

                return <Photos
                            src={item.img}
                            title={item.name}
                            key={'photo-' + (i++)}
                        />;
            });
	    return (
            <div className="imgs">
            {imgs}
            </div>
	    );
}
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #50 (permalink)  
Старый 01.05.2015, 23:21
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Причем <Photos может состоять ещё из десятка компонентов или из одного <img>, это реально круто, наследование в html
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Смишных картинок тред megaupload Оффтопик 3448 03.07.2023 09:47
Обсуждений тред cyber Оффтопик 2135 03.10.2018 08:10
Webpack'а тред nerv_ Сборка проекта, утилиты 58 07.05.2016 13:46
Github Atom'а тред melky Оффтопик 16 01.04.2015 07:44
Смишных видео с намеком тред godofjavascript Оффтопик 4 30.12.2012 23:50