2gis / slot

JavaScript фреймворк, позволяющий быстро и просто создавать модульные изоморфные приложения.
http://2gis.github.io/slot
BSD 2-Clause "Simplified" License
86 stars 10 forks source link

Слабая документация проекта #235

Open iDevPro opened 8 years ago

iDevPro commented 8 years ago

Добрый день, команда 2GIS.

Решил попробовать ваш фреймворк, однако начинаю наступать на грабли, похоже детские... 1) Добавил модуль, а вот как правильно его прописать тут: ./components/appState/conf.js до конца не ясно :)

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

iDevPro commented 8 years ago
exports.urls = {
    'news':{
        module:'news',
        history: true
    }
};

return: TypeError:Invalid injector for state:[object Object]

And,

exports.urls = {
    'news':'/news/:id'
};

return: TypeError: Invalid injector for state:/news/:id

But, this code work like need

exports['mainModule'] = 'hello';

// Страницы разработчиков. Например, по адресу localhost:3000/makeup приложение будет загружать модуль makeup в качестве главного
exports.devPages = {
    'makeup': { // slug
        module: 'makeup',
        history: false
    },
    'news': {
        module: 'news',
        history: true
    }
};
artem-malko commented 8 years ago
exports.urls = {
    '/news/:id': 'inject'
};

Этот конфиг позволит заинитить модули, инит которых должен произойти по изменению id новости в state.То есть когда в url будет вот так: http://localhost:3000/news/20. Код для инита модуля примерно такой:

// Внутри корневого модуля, метод changeState:

changeState: function(diff) {
    if ('news' in diff) {
        slot.init(...)
    } 
}
iDevPro commented 8 years ago

Добавил в news.js (или надо в другое место ?)

changeState: function(diff) {
    if ('news' in diff) {
        slot.init()
    } 
}

в config.js

exports.urls = {
    '/news/:id': 'inject'
};

Получил: Uncaught SecurityError: Failed to execute 'replaceState' on 'History': A history state object with URL 'http://news/3' cannot be created in a document with origin 'http://localhost:3000'.

P.s.: А если хочу по /news получить все новости ? P.s.p.s: Ставил Slot из npm P.s.p.s.p.s: Ошибка фиксится убиранием / перед news..

artem-malko commented 8 years ago

@iDevPro только хотел написать, что нужно слешик убрать)

iDevPro commented 8 years ago

Проблема в том что он в модуль вообще не заходит, потому что ни init, ни changeState не обрабатываются, так как console.log ))) пуст :(

Очень странно: slot@0.10.2

artem-malko commented 8 years ago

@iDevPro смотри, все работает примерно так: у тебя есть главный модуль, который указывается в конфиге проекта (exports['mainModule'] в config/base). Этот главный модуль будет интить модули по умолчанию, например, и слушать state в методе changeState и инитить модули для текущего стейта и diff. Каждый модуль так же может слушать изменения в стейете и как-то реагировать на это. То есть, у тебя есть некий корневой модуль, который инитит все остальное. От этого и надо плясать)

artem-malko commented 8 years ago

@iDevPro тут еще немного инфы: https://devday.ru/report/153

iDevPro commented 8 years ago

Если я правильно понимаю, то mainModule = index.(js/html/css) ? В нем я могу подключить модули navbar, container, и менять содержимое контейнера в зависимости от полученного стейта :(

Простите за глупые вопросы, но пока до меня толком не доходит как начать его использовать, с Ember чуть проще... но хочется перейти на наше, родное :)

iDevPro commented 8 years ago

artem-malko Спасибо. попробую разобаться через slot init todo :)

artem-malko commented 8 years ago

@iDevPro вот, что-то я забыл про него сказать)

iDevPro commented 8 years ago

Как добавить bootstrap в проект ? простым npm --save install bootstrap не решается потом, не решается так-же добавлением в папку public директории assets/bootstrap где лежат файлы bootstrap.min.css, bootstrap.min.js

Решил, но в браузере не видно его по умолчанию в ресурсах :)))

artem-malko commented 8 years ago

@iDevPro это уже не вопрос фреймворка) Поумолчанию, со слотом идет совсем простая сборка на gulp. Вы можете сами ее расширять так, как вам будет удобно.

iDevPro commented 8 years ago

Все равно пока не доходит как сделать приложение :) ToDo это одна страница в SPA )

artem-malko commented 8 years ago

@iDevPro смотри, в общем виде все выглядит так: У тебя есть главный модуль, который принимает решение на основе стейта, что заинитить в самом начале при первом запуске, и что делать, при изменении стейта. Каждый модуль тоже может инитить модули и принимать решение на основе стейта, что делать с самим собой и с детьми. Общаться все могут с помощью slot.notify, через главный модуль.

iDevPro commented 8 years ago
changeState: function(diff) {
      console.log(diff);
}

Если я правильно понимаю, то прописав этот код в root модуле, я должен в консоли увидеть diff, однако я не вижу ничего :(

artem-malko commented 8 years ago

Все верно. Только вам необходимо, чтобы что этот diff создовало. $appState.push по какой-нить ссылке. В TODO как раз есть примеры того, как в state что-то пропихнуть

iDevPro commented 8 years ago

Хитрость в том что в Todo, используются ссылки следующего вида http://domain.tld/filter/active Потому что в conf.js filter/:type, такие и у меня работает :) А вот простые ссылки вида http://domain.tld/about нет :)

myshov commented 8 years ago

@iDevPro привет!

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

По поводу вопроса. С простыми ссылками вида /about, /news в Slot работать можно, но так как эти ссылки должны друг друга взаимоисключать, т.е. URL не может быть вида /about/news, получается не очень элегантно. Например, если надо обработать два URL вида /about, /news, надо будет написать что-то вроде этого:

function activateModule(moduleName) {
  $appState.del('news');
  $appState.del('about');
  $appState.set(moduleName);
  $appState.push();
}

При большем количестве одиночных фрагментов URL эта функция также будет расти, что не очень хорошо, лучше стремится к простоте и краткости. Именно поэтому мы рекомендуем использовать для "страниц" одной категории обобщающий URL вида http://yoursite.tld/section/news, в этом случае никакой дополнительной обработки делать не надо.

Одиночные фрагменты в URL мы используем для флагов состояния приложения, если их необходимо сохранить между сеессиями и если они не исключают друг друга. В 2gis.ru, например, есть одиночный фрагмент 2gis.ru/global, который говорит о том, что приложение сейчас отображает карту мира.

Одиночный фрагмент внедрить в url можно, добавив в conf.js:

exports.urls = {
    'about': 'injectTrue'
};

И установив значение из кода:

$appState.set('about', true);
$appState.push();

Для проверки его наличия в приложении:

$appState.get('about');

Сделал небольшое тестовое приложение https://github.com/myshov/slotapp по мотивам /news, /about, надеюсь оно поможет еще больше разобраться в том как работать с фреймворком.

iDevPro commented 8 years ago

Спасибо. Попробую разобраться. Вот зачем нужны одиночные ссылки вида:

Вот как раз и не доходит как сделать, к примеру: /news - список всех новостей /news/1 - конкретная новость полным текстом /news/important - важные новости

iDevPro commented 8 years ago

Если верить данному: http://www.slideshare.net/DevDay/slot-good-parts-50970458 (40 слайд) То, http://domain.tld/news/1 должна вызвать функцию:

changeState: function(diff) {
            console.log(diff);
        }

которая выведет { news: { newsId: 1}}, а не {}

P.S.:

exports.urls = {
    'news/:newsId': 'inject',
    'players/:playerId': 'inject'
};
myshov commented 8 years ago

На слайде показаны результаты парсинга URL в стейт. Если вы переходите по ссылке http://domain.tld/news/1 в самом приложении узнать об id из URL можно обратившись к методу get $appState и обратвшись к свойству объекта- $appState.get('news').newsId. changeState в этом случае не срабатывает, он будет срабатывать только, если вы в приложении сами изменили состояние и "протолкнули" его в URL, например, вот таким образом:

$appState.set('news', {newsId: 2});
$appState.push()

и уже после этого

changeState: function(diff) {
    console.log(diff);
}

выведет в консоль то, что изменилось в appState, а именно { news: { newsId: 2}}

iDevPro commented 8 years ago

Спасибо за пояснение, однако странно что: // Обработка ссылок и кнопок 1) <a href="/news/all">News</a> 2) <a class="main__newsLink" href="/news/all">News</a>

Мне кажется оба варианта одно и тоже, однако:

// AppState такой AppState :( Вчера эксперементировал с AppState, внутри есть: state, lastState, curState

function showModule(module, moduleState) {
        slot.broadcast('*:dispose');
        $appState.set(module, moduleState);
        $appState.replace();
        slot.init(module);
        slot.rerender();
    }

1) текущий стейт не очищается а просто добавляется к уже имеющимся 2) state === curState === lastState ? O_o

Вопросы в следующем: В чем разница между переходом по ссылке и открытием сайта по ссылки ? Как получить текущий установленный мною state, без мусора от предыдущего ?

eventengine commented 8 years ago

Ребят, вопрос нубский - насколько ваш слот схож по структуре с Экспрессом? Просто хотели на вашем писать, отдали на анализ тем кто больше нас понимает - сказали нам что сыроват слот, а так как стек мы выбрали MEAN - решили не городить огород и писать на "искаропки". Но хочется конечно вас поддержать, бесспорно.

iDevPro commented 8 years ago

И снова я, с глупыми вопросами. Вторая попытка понять Slot ;)

Учитывая все выше изложенное, верно ли я понимаю: 1) Что модуль - это не блок который показывает список, а блок который показывает элемент списка? 2) Если модуль - это все же блок который показывает список, то вызвав /blockName/all я должен обработать all в самом блоке ?

iDevPro commented 8 years ago

Почему init todo отличается от init в оформлении модулей, к примеру в init todo есть $appState, которая, как я понял, отвечает на вопрос какое значение у стейта при заходе на сайт по урлу стейта news/1 или news/2