Создание современных Web
приложений на основе Catbee 3.0.0

Catbee Core Concepts
- Изоморфный Javascript фреймворк
- Написан в ООП стиле с применением Service Locator Pattern и Dependency Injection
- Следует принципам Unidirectional Data Flow
- Предлагает W3C Web Components подход для слоя представления
Немного о интерфейсных приложениях
Отличия от других приложений:
- Конечное количество состояний UI
- HTML вместо JSON/XML/YAML/ETC...
- Ярковыраженная событийная система
Основные хранилища состояний
- URL
- Cookie/LocalStorage/SessionStorage/...
- DOM
- Javascript Memory
HTML. Какой он бывает?
// Самый простой элемент
<div></div>
// Интерактивный элемент
<input type="text" />
// Сложный Web Component с Shadow DOM
<input type="number">
#shadow-root (user-agent)
<div id="text-field-container" pseudo="-webkit-textfield-decoration-container">
<div id="editing-view-port">
<div id="inner-editor"></div>
</div>
</div>
<div pseudo="-webkit-inner-spin-button" id="spin"></div>
</input>
HTML. Как его готовим мы?
<cat-button theme="blue" label="Заказать звонок">
<button class="_button_6v0cw_1 _blue_1gav3_36">
Заказать звонок
</button>
</cat-button>
HTML. Как его готовим мы?
this.$context.createComponent('button', {
constructor: Button,
props: {
label: 'Заказать звонок',
theme: 'blue'
}
})
.then((element) => {
// Element is:
// <cat-button>
// <button class="_button_6v0cw_1 _blue_1gav3_36">
// Заказать звонок
// </button>
// </cat-button>
});
Unidirectional Data Flow
Может быть знаком как CQRS + Event Sourcing

Data Flow Diagram
Пример сигнала
exports.basicSignal = [
setPageTitle,
setPageDescription
]
function setPageTitle (args, state) {
state.set(['page', 'title'], 'account.2gis.ru - очень крутой');
}
function setPageDescription (args, state) {
state.set(['page', 'description'], 'Все разработчики ЛК няши! :meow:')
}
Пример сигнала
exports.advancedSignal = [
setLoading, // Sync function
[ // Here we run parallel functions
getUser, { // Async function with 2 outputs success and error
success: [setUser], // Run if we call output.success in getUser
error: [setUserError] // Run if we call output.error in getUser
},
getNews, { // It's function will run paraller with getUser, like Promise.all
loaded: [setNews],
error: [setNewsError]
}
],
unsetLoading
]
function getUser (args, state, output) {
ajax.get('/url')
.then(function (response) {
output.success({ news: response });
}
.catch(function (response) {
output.error({ error: response.code });
})
}
Пример получения данных
// Child component
class Component {
render () {
return this.$context.getWatcherData().then((data) => data));
}
}
...
// Parent component
module.exports = {
constructor: Parent,
children: [
{
name: 'child',
component: child,
watcher: {
value: ['path', 'to', 'value']
}
}
]
}
Computed Fields
Computed Fields
state.set(['counter'], Baobab.monkey(
['todos'],
(todos = []) => {
return todos.filter((todo) => todo.status == 'active').length)
}
);
Computed Fields
state.set(['auction', 'UIState', 'isBidsButtonEnabled'], Baobab.monkey(
['permissions', 'adverts', 'bids'],
['auction', 'campaign', 'permissions', 'isAgreementAccepted'],
['auction', 'computed', 'isBidsChanged'],
['auction', 'computed', 'isBidsValid']
(isBidsEnabled, isAgreementEnabled, isBidsChanged, isBidsValid) =>
_.every([isBidsEnabled, isAgreementEnabled, isBidsChanged, isBidsValid])
));
Вопросы?
deck
By Kirill Kaysarov
deck
- 888