|
@@ -0,0 +1,98 @@
|
|
|
+function createStore(reducer){
|
|
|
+ let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
|
|
|
+ let cbs = [] //массив подписчиков
|
|
|
+
|
|
|
+ const getState = () => state //функция, возвращающая переменную из замыкания
|
|
|
+ const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
|
|
|
+ () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
|
|
|
+
|
|
|
+ const dispatch = action => {
|
|
|
+ const newState = reducer(state, action) //пробуем запустить редьюсер
|
|
|
+ if (newState !== state){ //проверяем, смог ли редьюсер обработать action
|
|
|
+ state = newState //если смог, то обновляем state
|
|
|
+ for (let cb of cbs) cb() //и запускаем подписчиков
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ getState, //добавление функции getState в результирующий объект
|
|
|
+ dispatch,
|
|
|
+ subscribe //добавление subscribe в объект
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function reducer(state, {type, ШО, СКОКА}){ //объект action деструктуризируется на три переменных
|
|
|
+ if (!state){ //начальная уборка в ларьке:
|
|
|
+ return {
|
|
|
+ пиво: 100, //{count: 100, price: 30}
|
|
|
+ чипсы: 100,//{count: 100, price: 25}
|
|
|
+ сиги: 100,
|
|
|
+// касса: 0, при покупках увеличивается
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === 'КУПИТЬ'){ //если тип action - КУПИТЬ, то:
|
|
|
+ //проверить на:
|
|
|
+ //наличие товара как такового (есть ли ключ в объекте)
|
|
|
+ //количество денег в action
|
|
|
+ //наличие нужного количества товара.
|
|
|
+ //и только при соблюдении этих условий обновлять state.
|
|
|
+ return {
|
|
|
+ ...state, //берем все что было из ассортимента
|
|
|
+ [ШО]: state[ШО] - СКОКА //и уменьшаем то, что покупается на количество
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
|
|
|
+}
|
|
|
+
|
|
|
+const store = createStore(reducer)
|
|
|
+//надо бы напилить цикл, который в select напихивает ассортимент.
|
|
|
+//возможно, если вы собираетесь выводить (и обновлять) количество,
|
|
|
+//это надо делать где в subscribe, иначе оно не будет обновлять количество
|
|
|
+let select = document.getElementById('goods')
|
|
|
+for(let key in store.getState()) {
|
|
|
+ let option = document.createElement('option')
|
|
|
+ option.innerText = key
|
|
|
+ option.value = key
|
|
|
+ select.append(option)
|
|
|
+}
|
|
|
+let quantity = document.getElementById('quantity')
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const купи = (ШО, СКОКА) => ({type: 'КУПИТЬ', ШО, СКОКА})
|
|
|
+
|
|
|
+buy.onclick = () => {
|
|
|
+ //достает выбранный товар и количество из DOM
|
|
|
+// store.dispatch(купи(....,....))
|
|
|
+ store.dispatch(купи(select.value, quantity.value))
|
|
|
+ console.log('steit', store.getState())
|
|
|
+}
|
|
|
+
|
|
|
+//запомнит функцию во внутреннем массиве cbs.
|
|
|
+//она будет запущена при любом успешном dispatch
|
|
|
+const unsubscribe = store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+//setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
|
|
|
+
|
|
|
+//происходит запуск редьюсера, который создает новый state.
|
|
|
+//dispatch запускает всех подписчиков из массива cbs
|
|
|
+
|
|
|
+let table = document.createElement('table')
|
|
|
+table.border = 1
|
|
|
+function smth(){
|
|
|
+ table.innerHTML = ''
|
|
|
+ for(let key in store.getState()) {
|
|
|
+ let tr = document.createElement('tr')
|
|
|
+ let tdKey = document.createElement('td')
|
|
|
+ let tdValue = document.createElement('td')
|
|
|
+ tdKey.innerText = key
|
|
|
+ tdValue.innerText = store.getState()[key]
|
|
|
+ tr.append(tdKey, tdValue)
|
|
|
+ table.append(tr)
|
|
|
+ }
|
|
|
+ shop.append(table)
|
|
|
+}
|
|
|
+smth()
|
|
|
+store.subscribe(smth)
|
|
|
+//setTimeout(() => store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3}), 5000)
|
|
|
+console.log(store.getState())
|