index.js 4.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. сиги: 100,
  26. // касса: 0, при покупках увеличивается
  27. }
  28. }
  29. if (type === 'КУПИТЬ'){ //если тип action - КУПИТЬ, то:
  30. //проверить на:
  31. //наличие товара как такового (есть ли ключ в объекте)
  32. //количество денег в action
  33. //наличие нужного количества товара.
  34. //и только при соблюдении этих условий обновлять state.
  35. return {
  36. ...state, //берем все что было из ассортимента
  37. [ШО]: state[ШО] - СКОКА //и уменьшаем то, что покупается на количество
  38. }
  39. }
  40. return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
  41. }
  42. const store = createStore(reducer)
  43. //надо бы напилить цикл, который в select напихивает ассортимент.
  44. //возможно, если вы собираетесь выводить (и обновлять) количество,
  45. //это надо делать где в subscribe, иначе оно не будет обновлять количество
  46. let select = document.getElementById('goods')
  47. for(let key in store.getState()) {
  48. let option = document.createElement('option')
  49. option.innerText = key
  50. option.value = key
  51. select.append(option)
  52. }
  53. let quantity = document.getElementById('quantity')
  54. const купи = (ШО, СКОКА) => ({type: 'КУПИТЬ', ШО, СКОКА})
  55. buy.onclick = () => {
  56. //достает выбранный товар и количество из DOM
  57. // store.dispatch(купи(....,....))
  58. store.dispatch(купи(select.value, quantity.value))
  59. console.log('steit', store.getState())
  60. }
  61. //запомнит функцию во внутреннем массиве cbs.
  62. //она будет запущена при любом успешном dispatch
  63. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  64. //setTimeout(unsubscribe, 10000) //отпишемся через 10 секунд, например
  65. //происходит запуск редьюсера, который создает новый state.
  66. //dispatch запускает всех подписчиков из массива cbs
  67. let table = document.createElement('table')
  68. table.border = 1
  69. function smth(){
  70. table.innerHTML = ''
  71. for(let key in store.getState()) {
  72. let tr = document.createElement('tr')
  73. let tdKey = document.createElement('td')
  74. let tdValue = document.createElement('td')
  75. tdKey.innerText = key
  76. tdValue.innerText = store.getState()[key]
  77. tr.append(tdKey, tdValue)
  78. table.append(tr)
  79. }
  80. shop.append(table)
  81. }
  82. smth()
  83. store.subscribe(smth)
  84. //setTimeout(() => store.dispatch({type: 'КУПИТЬ', ШО: 'пиво', СКОКА: 3}), 5000)
  85. console.log(store.getState())