Модульность во Vue.js и Vuex

Автор оригинала: Eze Henry
  • Перевод

image


При написании больших фронтенд-приложений управление состоянием может стать довольно сложной и утомительной задачей.


image


Для Vue.js был разработан плагин Vuex, предназначенный для управления состоянием. По умолчанию в нем выстроена следующая структура папок:


image
Структура папок в хранилище Vuex


Эту структуру папок можно было бы использовать в небольших приложениях, но в больших исходный код, скорее всего, будет выглядеть нечитаемо и некрасиво, а со временем с ним станет тяжело работать.


image
О да, я узнал это на собственном горьком опыте


Я бы рекомендовал структуру папок, в которой хранилище разбито на различные модули. Например:


image
Рекомендованная структура Vuex (прим. пер.: на этой картинке автор, вероятно, забыл добавить файл store/modules/user/mutations.js, т.к. он фигурирует далее в коде)


Эта структура папок разбивает хранилище на модули, у каждого из которых есть своя отдельная папка. Папка со всеми модулями находится там же, где и index.js, сгенерированный с помощью Vuex. Как и следовало ожидать, содержимое файла index.js нужно тоже поменять, например на такое:


import Vue from "vue";
import Vuex from "vuex";
import state from './state.js'
import actions from './actions.js'
import mutations from './mutations.js'
import getters from './getters.js'
import user from './modules/user/index.js'
Vue.use(Vuex);
export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters,
    modules: {
        user
    }
});

В этом примере я создал модуль «user», импортировал его в index.js, предоставленный библиотекой Vuex. Таким образом, модуль «user» был подключен к хранилищу, и теперь доступен.


Переходя к модулю «user» мы импортируем state, actions, getters и mutations в modules/user/index.js таким образом:


import state from './state.js'
import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
export default {
    namespaced: true,
    state,
    mutations,
    getters,
    actions,
}

Если вы заметили, полю namespaced было задано значение true. Это обусловлено тем, что в определенных обстоятельствах мы хотим иметь возможность указать, чтобы определенный модуль искал определенное действие, состояние или геттер. Идем дальше...


Состояние


Из-за перехода от стандартной структуры Vuex к модульной методы, через которые мы получали доступ к состоянию Vuex, нужно изменить. Например, мы не сможем получить доступ к полю userAvatar из состояния модуля «user» простым отображением поля userAvatar на поля объекта вычисляемых свойств (прим. пер.: под простым отображением понимается такой стандартный способ вызова функции mapState: ...mapState(['userAvatar'])}). Так что мы используем функцию mapState (прим. пер.: эта функция автоматически генерирует вычисляемые свойства) в скрипте компонента следующим образом:


import {mapState} from 'vuex'
export default {
    computed: {
        ...mapState({
            userAvatar: state => state.user.userAvatar
        })
    },
}

Выше показан рекомендованный метод получения доступа к состоянию модуля, которое бы выглядело так:


export default {
    userAvatar: "img-location"
};

Действия


Также нельзя ожидать, что действие из модуля «user» будет доступно простым отображением действий на поля объекта методов. Нам бы пришлось указать конкретный модуль, к которому мы пытаемся получить доступ, например:


import {mapActions} from 'vuex'
export default {
    methods: {
        ...mapActions("user", ["getUserInfo"]),
        userInfo() {
            this.getUserInfo()
            // вы могли бы либо отобразить это – как мы сделали выше (прим. пер.: вероятно, имеется в виду строчка <..mapActions("user", ["getUserInfo"]),>), либо вызвать в точности тем же способом, 
            // что использован ниже
            this.$store.dispatch('user/getUserInfo')
            // эти два метода выполняют одну и ту же задачу – вызов действия getUserInfo
        }
    },
}

Выше представлен предпочтительный метод доступа к действию из модульного Vuex в случае использования следующего файла с действиями:


export default {
    getUserInfo() {
        alert('Successful')
    }
}

Мутации


Мутации используются для синхронных функций и чаще всего используются для изменения состояния. Способ получения доступа к мутации также будет другим.


export default {
    methods: {
        setuserInfo() {
            let data = {
                name: 'Henry'
            }
            this.$store.commit('user/setUserInfo', data)
        }
    },
}

Выше представлен рекомендованный способ доступа к мутации в модульном Vuex при использовании такого файла с мутациями:


export default {
    setUserInfo: (state, data) => {
        state.user = data
    }
}

Геттеры


Геттеры подобны вычисляемому свойству компонента. Их используют для вычислений или фильтрации. Типичный случай использования геттеров – сортировка по отличиям в полях или по доступности полей, например:


export default {
    getActiveUsers: state => {
        return state.users.filter(x => x.active === true)
    }
}

Выше – рекомендованный способ объявления или записи геттера, при этом к нему можно получить доступ с помощью отображения геттеров на поля объекта вычисляемых свойств, например вот так:


import {mapState} from 'vuex'
export default {
    computed: {
        ...mapGetters('user', ['getActiveUsers'])
    },
}

Это был долгий путь, надеюсь, что у вас получилось использовать модульный Vuex и писать более чистый код.

Средняя зарплата в IT

110 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 8 851 анкеты, за 2-ое пол. 2020 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 12

    +1

    Так это же копипаста с официальной документации. Или в России уже запретили и ее?

      0
      А где вы увидели копипасту? Я не нашел… Ну, или я плохо искал
        –1
        Списался с автором оригинальной статьи и вот что он ответил по поводу вашего замечания: «Я читал про модульность в документации, и в своей статье попытался разъяснить этот материал другим разработчикам. Подход по сути тот же, что и в документации, но отличие в том, что каждый модуль в своей папке.»
        0
        Эх я думал автор еще и расскажет про рекомендуемую им структуру (каталогов) самого приложения, а то хочу начать изучать Vue и не могу определится со структурой каталогов проекта, может кто подскажет ссылки на проекты с адекватной структурой?
          0
          Посмотри на фреймворк NuxtJS, там готовая структура директорий.
            0
            Мне понравилось, спасибо

            Вот прямая ссылка если вдруг кому тоже надо

            Единственное не совсем раскрыт вопрос с каталогом «pages» они там предлагают писать так
            index.vue
            about.vue
            other.vue

            и писать портянки в одном файле, но это как мы знаем сферический конь в вакууме и страница может быть довольно сложной и тут мне понравилась вот такая идея:
            modules
            __{moduleName}/
            ____index.js
            ____routes.js
            ____components/
            ______{ModuleName}List.vue
            ______{ModuleName}View.vue
            ______{ModuleName}Form.vue
            __...


            Позволяет разбить портянку всей страницы на компоненты, которые будут использоваться только на одной странице и никогда на других
              0
              Объясните, в чем профит размещать папки проекта (components, pages и т.д. ) на одном уровне с node_modules?
            0

            Извините. А почему бы сразу автоматически подключать модули? Сканируя папки с модулями по файлу index. А в модуле, в файле индекс, автоматически импортировать гетеры сетеры мутации и т. п. И про эту реализацию, описанную мной выше, уже есть куча статей. Я ни коем образом не хочу вас как либо обидеть, мне интересен смысл данной статьи, почему?

              0
              В статье тоже геттеры, сеттеры, мутации в index.js модуля импортируются, если не ошибаюсь. Да, сканирования и автоматического импорта нет, модули импортируются вручную, но как альтернативный вариант, без сканирования — разве не имеет право на жизнь? Может быть автору оригинала нравится именно вручную?
              0

              Видимо фломастеры нам разные нравятся

                0
                vuex конечно вещь не заменимая, но когда дело доходит до реальных огромных вложенных данных — то лучше использовать надстройку vuex-orm
                  0
                  А если не большие, но и не маленькие, то возможно подойдет vuexok

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое