Pull to refresh

Comments 67

class MySecondComponent extends MyComponent  {
 constructor(...args) {
    super(...args);
    this.scope.example = 'Goodbye World';
  }
  myOwnMethod() {}
}

Как в этом случае добавляются/описываются дополнительные зависимости для MySecondComponent?


Во-вторых, области видимости разметки также наследуются.

Прототайпинг скоупа как раз ангуляровская фишка (точнее обычный JS прототайпинг), от которой лучше отказаться, так же лучше отказаться от любых вещей завязанных на специфику фреймворка, передавать все явном виде через атрибуты. Компоненты по-моему мнению компоненты должны быть независимыми/изолированными.

1) Не совсем понял, что имеется ввиду под дополнительными зависимостями?
2) Тут согласен, но это скорее просто бонус, разные ситуации бывают. Про то как сделать компоненты модульными я в статье описал.
имеется в виду ангуляровское внедрение зависимостей — Dependency Injection
UFO just landed and posted this here
 <for in="${ this.data }">
    <loop>${ this.loopIndex } => ${ this.loopKey} => ${ this.loopValue.title  }</loop>
  </for>

Синтаксис так себе, интуитивно не понятный, по сути скрестили кота с ежом без без поддержки кота и ежа. И вызовы конструктора базового класса, тоже не удобно, нужны обертки. Сверху правы берите Vue и не мучайтесь

Весь синтаксис это доллар и фигурные скобки в стиле es6, причем во всех кейсах )
UFO just landed and posted this here
Неудачный пример получился наверное, согласен ) Стрелки просто часть html
UFO just landed and posted this here

Имелось в виду, что стрелки — часть выводимого HTML, они будут отображаться на странице.

Именно! Vue — это то, каким должен был быть ангуляр.
все популярные фреймворки суть одно и то же: крайне не организованный код и hardcoded html, которые невозможно использовать в другом проекте

графический интерфейс очень прост и имеет простые стандартные элементы и функционал, поэтому кодирование бизнес логики не должно быть таким сложным

Увидел stage-0 перестал читать дальше. Если stage-0 пускать в продакш, то так далеко не уехать.

Подозреваю, что автор просто не в курсе, что class fields уже давно не stage-0, а 2. Стадии показываются тут. Stage-2 будет достаточно, чтобы код из статьи собрался.


Да и вообще, набор es2015+stage-0 это очень странно. То есть мы берем 2015, пропускаем 2016, 2017 (которые уже тоже часть стандарта и есть в некоторых браузерах), зато берем всякую дичь из stage-0.


Сам Babel рекомендует использовать babel-preset-env, который будет обновляться по мере добавления новых фич в стандарт, и также будут выпиливаться преобразования для штук, которые уже нативно есть в браузерах (список поддерживаемых браузеров настраивается)

Можно собрать как удобно, просто хотел предупредить о свойствах класса в описании.

Что-то я не стал бы доверять фреймворку, разработчик которого говорит "возьмите какие-нибудь настройки Babel", вместо минимально необходимого набора плагинов.

Суть фреймворка-то не в том как скомпилировать какое-то конкретное приложение, можно хоть в head его подключить и все будет работать.
Потому что это библиотека, а не фреймворк :).
Сайт лежит в 502-й. Видно не ожидали вы местного наплыва :)

По теме: первое впечатление — Vue.js.
Но, честно говоря, мне больше нравится именно React на который я пересел с Ангуляра (первого). В особенности нравится JSX за его 100% совместимость с JS. А все эти прилепленные директивы и циклы через html жутко неудобны, как по мне.

В статье вы сначала пишите, что скрестили Ежа с Коноплей, но потом эта мысль как-то сразу теряется. В чем преимущества перед обоими фреймворками? Их потому и два, что они офигеть какие разные. И не нужно это менять.

Кстати, везде в конструкторе присутствет super(...args);
Нужно этого как-то избегать, либо добавить аналог componentDidMount(), а то забыл поставить — и что будет?
сайт лежал — обнаружил memory leak в jsdom, буду искать решение.

аналог componentWillMount — created
аналог componentDidMount — compiled

То есть конструктор можно вообще и не писать.

Про шаблоны совсем ничего не написано. Как написать такой компонент, который из этого html:


<hello-component name="Tester" description="test user" />

сделает вот такой:


<div>
  <h1>Hello, tester!<h1>
  <p>test user</p>
</div>

?

class HelloComponent extends Akili.Component {
 static templateUrl = './path/to/template';
}


или

class HelloComponent extends Akili.Component {
  static template = `<div>
    <h1>Hello, tester!<h1>
    <p>test user</p>
  </div>`;
}

А что будет, если внутри HelloComponent будет разметка:


<hello-component>Текст внутри</hello-component>

Шаблон ее перезапишет или добавится в конец?

перезапишет, но если содержимое нужно куда-то вставить, то можно использовать свойство скоупа .__content

class HelloComponent extends Akili.Component {
  static template = `<div>
    <h1>Hello, tester!<h1>
    <p>${ this.__content }</p>
  </div>`;
}


В приме выше выражение ${ this.__content } заменится на Текст внутри
.resolved() Этот метод, насколько я знаю, не имеет аналогов в известных мне фреймфорках.

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


В React это делается тривиально


class ComponentWithLoader extends React.Component {
  state = { loading: false, data: null };

  componentDidMount() {
     this.setState({loading: true})
     loadData().then((data) => this.setState({loading: false, data: data}));
  }

  render() {
    if(this.state.loading) {
       return <Loader />
    }
    return <div>{/*какой-то контент*/}</div>
  }
}

При желании можно завернуть в переиспользуемый компонент, или взять уже готовый.
Тащить это в ядро фреймворка смысла нет.

Смысл все же есть. Бывают, например, группы компонентов, когда их несколько и они завязаны друг на друге. Например посмотрите реализацию табов.

Родительский компонент может захотеть что-то сделать с дочерними. Метод resolved гарантирует, что в нем все дочерние будут полностью скомпилированы и тогда к ним можно обратиться через систему коммуникации компонентов.

Посмотрел на реализацию табов, понятнее не стало. В исходном коде нет ни одной асинхронной операции, откуда там resolved нужен, совсем не ясно

Дело в том что компиляция идет сверху вниз по дереву, элемент за элементом, поэтому если нужно что-то сделать с дочерними элементами из родительского после его компиляции, то мы также используем resolved. В нем все дочерние компоненты будут гарантировано скомпилированы, в этом его смысл.

В целом, метод resolved используем когда нужен доступ к детям.

Такой лайфцикл позволяет работать с компонентами, почти так как это происходит в DOM:
В примерах ниже левая и правая части эквивалетны:

el.querySelector('input') => component.child('input')
el.querySelectorAll('input') => component.children('input')
el.parentNode => component.parent()

Разница только в том, что все методы справа возвращают не элемент, а компонент.
В компонентах Akili есть много разных методов для взаимодействия друг с другом

class ParentComponent extends Akili.Component {
  resolved() {
     let childComponent = this.child('child');

     console.log(childComponent.scope.example); //  'Hello World'

     childComponent.scope.example = 'Goodbye World'; // в разметке значение также поменяется
  }
}

class ChildComponent extends Akili.Component {
  compiled() {
    scope.example = 'Hello World';
  }
}

Akili.component('parent', ParentComponent); 
Akili.component('child', ChildComponent); 

<parent>
   <child>${ this.example }</child>
</parent>


childComponent.scope.example = 'Goodbye World'; — про инкапсуляцию, видимо, никто не слышал… Ну нельзя же такие вещи приводить в качестве примера!

А в чем тут проблема? Компонент это по сути экземпляр класса, а scope это public property.

А с какого перепугу scope является public property?

По хорошему, компонент должен быть «черным ящиком с парой кнопок» с мнимальным интерфейсом, что-б никто не мог внутрях ковырятся, иначе это будет повышать риск хаоса.

А можно не заниматься ерундой с ручным управлением индикаторами ожидания, воспользовавшись реактивным программированием.


Ваш, код мог бы выглядеть примерно так:


class ComponentWithLoader extends MyComponent {

  @ $mol_mem()
  render() {
    return $mol_http.request( '/data.json' ).json().map( item => <Item item={ item } /> )
  }

}

Так а что будет видеть пользователь, пока data.json загружается?

Индикатор ожидания, очевидно. Не нравится стандартный, всегда можно запилить свой:


class ComponentWithLoader extends MyComponent {

  @ $mol_mem()
  render() {
    try {
      return $mol_http.request( '/data.json' ).json().map( item => <Item item={ item } /> )
    } catch( error ) {
      return <StatusIndicator error={ error } />
    }
  }

}

А каким образом неперехваченное исключение превращается в индикатор ожидания?

Точно таким же try-catch, но там, где вызывается render (это не в реакте).

Что-то это еще больше все запутывает


catch блок — это про ошибку после загрузки. А в процессе что будет показываться?

У него в фреймворке состояние "в процессе" считается исключительным. Метод render вычисляется два раза, первый раз отваливается с исключением, а второй раз запускается автоматически когда запрос выполнится. В этот раз метод request не будет делать нового запроса к серверу, а вернет значение, полученное в прошлый раз.


По-своему красивая идея — жаль только метод request делает не то как называется.

Метод с аннотацией mol_mem (мемоизация, как я предполагал), вызывается несколько раз и выдает разный результат?


Извините, но мне с таким подходом точно не по пути.

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


В Knockout такая штука называется pureComputed, в MobX — computed.

Как по мне, jsx шикарен, а сам react невероятно элегантен. Нет ни одной задачи, которой я не смог бы решить с его помощью или с помощью библиотеки, которую можно к нему прикрутить.


В любом случае, библиотека хорошая, "но использовать я ее, конечно, не буду". По крайней мере к реакту у меня доверия всяко больше. Как минимум, ответов на stack overflow больше.


Желаю дальнейших успехов в разработке)

Это всё конечно прекрасно, только вот не совсем понятно зачем всё это. Кто хотел получить Angular + React, получили Vue, иногда мне кажется, что она только для этого и придумана была. Но это, очередной проходной фреймворк.
У вас получился Polymer. Пока чуть менее сложный, но это вы ещё до dom-repeat, обработки массивов, атомарных изменений нескольких полей и оптимизации вычисляемых байндингов не дошли. Ну и без Shadow DOM, HTML-imports и изоляции CSS у вас реализация. А так — один в один «стиль» «фреймворка» (правильнее — библиотеки). Polymer себя позиционирует таки компонентной библиотекой, и вам следует тоже, ибо «простота» и «отсутствие магии» — это и есть отсутствие навязываемой жёсткой структуры проекта, предлагается лишь способ «нарезки» кода на компоненты, а архитектуру из этих компонентов программисту придётся сочинять самостоятельно. Ну и ценность таких библиотек зависит от их заполненности «подходящими» друг к другу как пазлинки готовыми базовыми компонентами, и тут Polymer вас тоже сильно опережает, простой чат (при готовом бэке) можно собрать вообще без кода, только путём связывания атрибутов готовых компонентов в разметке друг с другом (там есть «невизуальные» компоненты типа компонента обеспечивающего роутинг или AJAX-запросы к серверу).

Призываю присоединиться к Polymer, работы там ещё куча :).
(Прошу прощения, dom-repeat и массивы у вас поддерживаются, роутинг и аякс-запросы тоже в готовых компонентах предложены, поторопился комментировать — теперь я уверен на 100%, что вы вдохновлялись Полимером :))
> Что будет если скрестить React и Angular?

Reangular? Anact?
Regular =) Была идея так назвать… )

Что-то, как мне кажется, тут была нарушена сама суть понятия "компонент". Компонентом применительно к UI обычно называют обособленную часть интерфейса, обладающую своим [внешним] видом, состоянием и поведением.


Здесь же "шаблонная" часть компонента вытащена наружу, компоненту остались только состояние и поведение. Это уже не компонент получается, а контроллер из старого AngularJS.

Компонент = логика + шаблон + имя. По имени один компонент может использовать в своём шаблоне другие компоненты. Всё нормально тут с компонентностью, вроде. (Упомяну опять «свой любимый» Polymer, в нём благодаря HTML-imports действительно более «железобетонно» «нарезаются» компоненты, HTML является контейнером и для разметки, и для скриптов, и для стилей, которые, конечно, можно разнести и на отдельные файлы, оставив в HTML ссылки на них. Плюс ко всему этому получается проще сборка — tree-shaking становится действительно tree — сборщик-«вулканизатор» напрямую из построенного импортами DOM-дерева получает всю иерархию зависимостей без необходимости анализировать JS-код.)
Компонент = логика + шаблон + имя.

Покажите мне шаблон у вот этого компонента:


class MyComponent extends Akili.Component {
  constructor(el, scope) {
    super(el, scope);
    scope.example = 'Hello World';
  }
}
Ничего страшного, если шаблон является опциональным аспектом компонента (для организации чего-нибудь типа HOC из Реакта или Behaviors из Полимера, например :)). Компонент не обязан быть визуальным.

Для решения подобных задач, навскидку, на ум приходят варианты сделать это с помощью нативных кастомных элементов или Polymer 2 или Vue.js ...etc. Что я должен знать о Akili, чтобы рассматривать его в качестве одной из альтернатив? В представленном описании я ничего такого не увидел, что я упускаю?

  • C react сравнили, с angular тоже, а по что aurelia обидели?
  • Какие проблемы вы решали и решили?
  • Какие будут аргументы против фразы "yet another framework"?
  • Что с перфомансом, где бенчи?
  • Ну и, наконец, где работающий туду-лист?
Примитивный todo есть на главной странице, хотя довольно многословен.
Через секунду значение переменной изменится и в объекте и в шаблоне.
Как отслеживается изменения?

Работают и отслеживаются ли «js» выражения в шаблоне?, наподобии
${a+b + ' ' + foo(c) + bar()}


Зачем нужен scope если есть this? особенно если оно «смешивается» в шаблоне.

    <for in="${ this.data }">

Можно ли сделать вложенный цикл и использовать данные родительского цикла во внутреннем?
Как отслеживается изменения?

Изменения отслеживаются с помощью механизма Proxy.

Работают и отслеживаются ли «js» выражения в шаблоне?

Да, отслеживаются все выражения где есть хоть какая-то переменная скоупа

Зачем нужен scope если есть this?

this в html это и есть scope. Поскольку скоуп был придуман как область видимости разметки, то в ней он является контекстом. В компоненте же есть ссылка на на него, в свойстве scope.

Можно ли сделать вложенный цикл и использовать данные родительского цикла во внутреннем?

Да, каждый скоуп имеет свойство .__parent — ссылку на родительский

Также, подробное описание всех возможностей, включая некоторые тонкости, можно найти в документации.
Изменения отслеживаются с помощью механизма Proxy.
ok, оно есть в 72% браузеров, в IE вероятно не появится никогда (в edge оно есть).

this в html это и есть scope.
Выглядит как лишняя сущность, было бы красивее разместить данные в this он бы и был this в html.

Да, отслеживаются все выражения где есть хоть какая-то переменная скоупа
Даже не так — если меняется любая отслеживаемая переменная, то вы делаете полный dirty-checking — проверяете все отслеживаемые переменные. При этом если данные в scope меняются, которые выводятся через функцию ${this.fullName()} — то обновления не происходит, недоработка.

Итого: Идет проверка всего на каждое изменение — повышенная нагрузка, хотя Proxy позволяет реагировать точечно, с другой стороны эта «проверка всего» пропускает некоторые типы биндингов в html — хотя у vue.js такая же проблемма, видимо не сильно напрягает, и третье Proxy не поддерживается больщой долей браузеров, как результат — рановато для боя.

Но для старта неплохо, все фреймворки с чего-то начинали.

Кстати, если при вызове выражения биндингов будете передавать this как параметр вместо подмены this, то они будут работать на прядок быстрее.
Выглядит как лишняя сущность, было бы красивее разместить данные в this он бы и был this в html.

Не совсем, в выражениях может быть что угодно, хоть ${ console.log('Hello') } хоть ${ window.location.href }
Область видимости по умолчанию весь window. Если нужно изменить это поведение, то достаточно дописать метод Component.parse как вам надо.
Даже не так — если меняется любая отслеживаемая переменная, то вы делаете полный dirty-checking — проверяете все отслеживаемые переменные. При этом если данные в scope меняются, которые выводятся через функцию ${this.fullName()} — то обновления не происходит, недоработка.

Данные которые будут в функции тоже начнут отслеживаются. Слежка происходит не на уровне парсинга этой строки. Тут все гораздо хитрее.

И еще момент, хоть отслеживается и каждое свойство скоупа отдельно, но синхронизация с шаблоном происходит группами. То есть если пройтись циклом и изменить 1000 значений в скоупе, то произойдет всего 1 операция изменения разметки, а не 1000.

Данные которые будут в функции тоже начнут отслеживаются. Слежка происходит не на уровне парсинга этой строки. Тут все гораздо хитрее.
Что-то не работает: http://jsfiddle.net/lega911/kw3f2mx2/ — fullName не обновляется.

Странно, в другом примере у меня было полное сканирование, в этом нет.
Область видимости по умолчанию весь window.
Это не желательно, т.к. в шаблон может попасть всякая бяка из вне.
Да, по поводу биндинга функции в шаблоне вы правы. Я в своем время долго решал какой вариант оставить. Почему-то запомнилось как будто оставил вариант с учетом всех вызовов.

Сейчас прикинул все варианты и вернулся к тому же. Выполнять функцию снова все-таки лучше при изменении аргументов, а не содержимого тела.

Спасибо за концентрацию внимания на этом моменте, я добавил возможность биндинга функции в шаблоне и по изменению аргументов и по телу. Теперь ваш пример должен работать.
Посмотрел примеры, вы создали странный vue 2.

Это было написано просто для веселья?
Возможно, Вам стоит пересмотреть парадигму разработки, придумать что-то новое, мне это кажется интереснее, чем соединять готовые фреймворки.

image
UFO just landed and posted this here
Sign up to leave a comment.

Articles