<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="style.css"> </head> <body> <div id="parampampam"> <div class="shop"> <select id='range'> <option value="пиво">Пиво</option> <option value="чипсы">Чипсы</option> <option value="сиги">Сиги</option> </select> <input type='number' id='amount1' placeholder='количество' /> <input type='number' id='money' placeholder='сумма' /> <button id='buy'>Купить</button> </div> <div id="tovar"> </div> <div id="price"> </div> <p id="kassa">Собираюсь построить Зикурат: </p> </div> <script> setTimeout(function () { let parent = document.getElementById("price"); parent.lastElementChild.remove(); store.dispatch({ type: "КУПИТЬ", ШО: "пиво", СКОКА: 0 }); }, 1); setTimeout(function () { let parent = document.getElementById("tovar"); parent.lastElementChild.remove(); store.dispatch({ type: "КУПИТЬ", ШО: "пиво", СКОКА: 0 }); }, 1); function reducer(state, { type, ШО, СКОКА, ДЕНЬГИ }) { //объект action деструктуризируется на три переменных if (!state) { //начальная уборка в ларьке: return { пиво: { count: 100, price: 23 }, чипсы: { count: 100, price: 18 }, сиги: { count: 100, price: 41 }, касса: 0, } } if (type === 'КУПИТЬ' && СКОКА >= 0) { //если тип action - КУПИТЬ, то: if (state[ШО].count >= СКОКА) { if (money.value >= (state[ШО].price * СКОКА)) { return { ...state, //берем все что было из ассортимента [ШО]: { count: state[ШО].count - СКОКА, price: state[ШО].price }, //и уменьшаем то, что покупается на количество касса: state.касса + +money.value // state[ШО].price * СКОКА() } } else { alert("Нужно больше золота!") } } else { alert('Извините товар едет!') } } else { alert('Наверное вам хватит '); } return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть } 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 в объект } } const store = createStore(reducer) //запомнит функцию во внутреннем массиве cbs. //она будет запущена при любом успешном dispatch const unsubscribe = store.subscribe(() => console.log(store.getState())) // setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например //происходит запуск редьюсера, который создает новый state. //dispatch запускает всех подписчиков из массива cbs store.dispatch({ type: 'КУПИТЬ', ШО: "пиво", СКОКА: 0 }) // const buy = (ШО, СКОКА) => ({ type: 'КУПИТЬ', ШО, СКОКА }) for (let [good, amount] of Object.entries(store.getState())) { console.log(good, amount); let p = document.createElement("p"); let p1 = document.createElement("p") p.innerHTML = `Количество ${good}: ${amount.count}`; p1.innerHTML = `(Цена-${amount.price})` price.append(p1) tovar.append(p); buy.onclick = () => { store.dispatch({ type: "КУПИТЬ", ШО: range.value, СКОКА: amount1.value }); kassa.innerHTML = "Собираюсь построить Зикурат: " + store.getState().касса }; store.subscribe( () => (p.innerHTML = `Количество ${good}: ${store.getState()[good].count }`) ); } </script> </body> </html>