123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- <header>cart reducer</header>
- <body>
- <div id="testDiv">
- Test
- </div>
- <script>
- function cartReducer(state = {}, action) { // диспетчер обработки
- switch (action.type) {
- case 'CART_ADD':
- if (action.count >= 0) {
- let newState = { ...state };
- let { count } = state[action.good._id] ?? { count: 0 };
- newState[action.good._id] = { count: action.count + count, good: { ...action.good } }
- return newState;
- }
- case 'CART_SUB':
- if (action.count >= 0) {
- let newState = { ...state };
- let { count } = state[action.good._id] ?? { count: 0 };
- if (count >= action.count) {
- newState[action.good._id] = { count: action.count - count, good: { ...action.good } }
- return newState;
- }
- }
- break;
- case 'CART_DEL':
- {
- let newState = { ...state };
- delete newState[action.good._id];
- return newState;
- }
- case 'CART_SET':
- {
- let newState = { ...state };
- newState[action.good._id] = { count: action.count, good: { ...action.good } };
- return newState;
- }
- case 'CART_CLEAR':
- return {};
- }
- return state;
- }
- 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, которая удаляет подписчика из списка
- function dispatch(action) {
- if (typeof action === 'function') { //если action - не объект, а функция
- return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
- }
- 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 actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count: count, good: good });
- const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good }); //Уменьшение количества товара. Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
- const actionCartDel = (good) => ({ type: 'CART_DEL', good }); //Удаление товара. Должен удалять ключ из state
- const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good }); //Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
- const actionCartClear = () => ({ type: 'CART_CLEAR' }); //Очистка корзины. state должен стать пустым объектом {}
- const store = createStore(cartReducer)
- store.subscribe(() => {
- console.log(store.getState())
- });
- store.dispatch(actionCartAdd({ _id: 'пиво', price: 50 }))
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 1}}
- store.dispatch(actionCartAdd({ _id: 'чипсы', price: 75 }))
- // {
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 1},
- // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 1},
- //}
- store.dispatch(actionCartAdd({ _id: 'пиво', price: 50 }, 5))
- // {
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 6},
- // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 1},
- //}
- store.dispatch(actionCartSet({ _id: 'чипсы', price: 75 }, 2))
- // {
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 6},
- // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 2},
- //}
- store.dispatch(actionCartSub({ _id: 'пиво', price: 50 }, 4))
- // {
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 2},
- // {чипсы: {good: {_id: 'чипсы', price: 75}, count: 2},
- //}
- store.dispatch(actionCartDel({ _id: 'чипсы', price: 75 }))
- // {
- // {пиво: {good: {_id: 'пиво', price: 50}, count: 2},
- //}
- store.dispatch(actionCartClear()) // {}
- </script>
- </body>
|