index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. function createStore(reducer){
  2. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  3. let cbs = [] //массив подписчиков
  4. const getState = () => state //функция, возвращающая переменную из замыкания
  5. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  6. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  7. const dispatch = action => {
  8. const newState = reducer(state, action) //пробуем запустить редьюсер
  9. if (newState !== state){ //проверяем, смог ли редьюсер обработать action
  10. state = newState //если смог, то обновляем state
  11. for (let cb of cbs) cb() //и запускаем подписчиков
  12. }
  13. }
  14. return {
  15. getState, //добавление функции getState в результирующий объект
  16. dispatch,
  17. subscribe //добавление subscribe в объект
  18. }
  19. }
  20. function reducer(state, {type, ШО, СКОКА, БАБОС}){ //объект action деструктуризируется на три переменных
  21. if (!state){ //начальная уборка в ларьке:
  22. return {
  23. // пиво: 100, //{count: 100, price: 30}
  24. // чипсы: 100,//{count: 100, price: 25}
  25. пиво: {count: 100, price: 30},
  26. чипсы: {count: 100, price: 25},
  27. сиги: {count: 100, price: 50},
  28. касса: 0, //при покупках увеличивается
  29. }
  30. }
  31. if (type === 'КУПИТЬ' &&
  32. state[ШО] && СКОКА > 0 &&
  33. СКОКА <= state[ШО].count && БАБОС >= state[ШО].price){ //если тип action - КУПИТЬ, то:
  34. //проверить на:
  35. //наличие товара как такового (есть ли ключ в объекте)
  36. //количество денег в action
  37. //наличие нужного количества товара.
  38. //и только при соблюдении этих условий обновлять state.
  39. console.log('bang')
  40. console.log(store.getState())
  41. state.касса += +БАБОС
  42. return {
  43. ...state, //берем все что было из ассортимента
  44. [ШО]: {count: state[ШО].count - Math.floor(СКОКА), price: state[ШО].price },//и уменьшаем то, что покупается на количество
  45. //[касса]: state[касса] + БАБОС,
  46. }
  47. }
  48. return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
  49. }
  50. const store = createStore(reducer)
  51. //надо бы напилить цикл, который в select напихивает ассортимент.
  52. //возможно, если вы собираетесь выводить (и обновлять) количество,
  53. //это надо делать где в subscribe, иначе оно не будет обновлять количество
  54. let select = document.getElementById('goods')
  55. for(let key in store.getState()) {
  56. if (key === 'касса') continue;
  57. let option = document.createElement('option')
  58. option.innerText = key
  59. option.value = key
  60. select.append(option)
  61. }
  62. let quantity = document.getElementById('quantity')
  63. let cash = document.getElementById('cash')
  64. const купи = (ШО, СКОКА, БАБОС) => ({type: 'КУПИТЬ', ШО, СКОКА, БАБОС})
  65. buy.onclick = () => {
  66. //достает выбранный товар и количество из DOM
  67. // store.dispatch(купи(....,....))
  68. store.dispatch(купи(select.value, quantity.value, cash.value))
  69. console.log('steit', store.getState())
  70. }
  71. //запомнит функцию во внутреннем массиве cbs.
  72. //она будет запущена при любом успешном dispatch
  73. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  74. //setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
  75. //происходит запуск редьюсера, который создает новый state.
  76. //dispatch запускает всех подписчиков из массива cbs
  77. let table = document.createElement('table')
  78. function drawTable(){
  79. table.innerHTML = ''
  80. table.insertAdjacentHTML('afterbegin', `
  81. <tr>
  82. <th>Товар</th>
  83. <th>Кол-во</th>
  84. <th>Стоимость</th>
  85. </tr>
  86. `)
  87. for(let key in store.getState()) {
  88. if(key === 'касса') continue;
  89. let tr = document.createElement('tr')
  90. let tdKey = document.createElement('td')
  91. let tdCount = document.createElement('td')
  92. let tdCost = document.createElement('td')
  93. tdKey.innerText = key
  94. tdCount.innerText = store.getState()[key].count
  95. tdCost.innerText = `${store.getState()[key].price} денег`
  96. tr.append(tdKey, tdCount, tdCost)
  97. table.append(tr)
  98. }
  99. table.insertAdjacentHTML('beforeend', `
  100. <tr>
  101. <th>Касса</th>
  102. <td>${store.getState().касса}</td>
  103. </tr>
  104. `)
  105. shop.append(table)
  106. }
  107. drawTable()
  108. store.subscribe(drawTable)
  109. //setTimeout(() => store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3}), 5000)
  110. console.log(store.getState())