Как правильно заказать звонки с помощью Vue / Vuex - PullRequest
2 голосов
/ 30 января 2020

Ниже приведен скелетный код, который демонстрирует проблему, связанную с принудительным порядком вызовов. Мне нужен следующий порядок:

  • Пользователь вызывает Foo. vue's someLocalMethod ().
    • Флаг установлен таким образом, чтобы Bar узнал о внесении изменений.
  • Этот флаг вызовет наблюдателя Bar.vues на go вперед и сделает некоторые работы.
    • Когда работа будет завершена, будет снят флаг
  • Foo. Функция someLocalMethod () vue обнаружит, что флаг был снят, и продолжит работу с его работа

Следует отметить, что и Бар, и Фу выполняют работу, которая меняет хранилище, поэтому файлы связаны (вместо того, чтобы использовать хранилище как флаг между обоими файлами).

Я предполагаю, что есть намного лучший / более чистый способ приблизиться к тому, что я делаю, но я не могу полностью указать на это. Код показан ниже.

Бар. vue

computed: {
  ...mapGetters('store', ['getSomeFlag']),
},
methods: {
  ...mapMutations('store', ['setSomeFlag']),
},
watch: {
  getSomeFlag(newValue) {
    if (newValue === true) {
      console.log('Flag is set. Going to do work');
      doWorkRelevantToBarPage();
      setSomeFlag(false);
    }
  }
}

Foo. vue

methods: {
  ...mapActions('store', ['someStoreCall']),
  ...mapMutations('store', ['setSomeFlag']),

  someLocalMethod(someData) {
    this.setSomeFlag(true);
    // somehow wait until Bar.vue's watcher becomes aware of it and completes it's own work
    this.someStoreCall(someData);      
  }
},

store. js

state: {
  someFlag: false,
  data: { 
    // Can be tons of nested structures, properties, etc
  },
},
getters: {
  getSomeFlag: (state) => state.someFlag,
},
mutations: {
  setSomeFlag(state, value) {
    state.someFlag = value;
  },
},
actions: {
  async someStoreCall({dispatch, commit, state}, data) {
    console.log('In someStoreCall');
  }
},

Ответы [ 2 ]

1 голос
/ 30 января 2020

Простое решение

Проблема в том, что Foo.vue, по сути, пытается запустить метод doWorkRelevantToBarPage в Bar.vue, который, вероятно, проще всего сделать с использованием шины событий, как предложено в другом ответе , но использование шины событий не является хорошей идеей, если вы хотите создавать большие / масштабируемые приложения с vue. js

Проблема заключается в подходе

с doWorkRelevantToBarPage Я предполагаю, что вы, скорее всего, захотите изменить какое-либо состояние, хранящееся в Bar.vue, или запустить другие методы, которые это делают. Теперь, когда у вас есть этот метод, вы хотите запустить его из Foo.vue, но это кажется неправильным подходом (особенно если вы хотите использовать vuex), вы видите, что вы по сути пытаетесь изменить состояние компонента извне, которое в большинстве случаев не ' Хорошая идея.

Использование Vuex

Ниже описаны действия, которые вы можете предпринять, чтобы адаптировать свой код для использования vuex

  1. Переместить любое состояние, которое Foo.vue требуется внешнее изменение в магазине.
  2. Создание мутаций и геттеров для состояний, которые вы поместили в магазине
  3. Подключите геттеры к вашему Bar.vue компоненту
  4. Создать действие, которое фиксирует необходимые мутации, как показано здесь (выберите более описательное имя):
updateBarData({commit, dispatch}, ...args) {
  commit('mutation1')
  commit('mutation2')
  commit('mutation3')
  dispatch('action1')
  dispatch('action2')
  // ... other logic
}
Добавьте действие к Foo.vue
methods: {
  ...mapActions('store', ['someStoreCall', 'updateBarData']),
  someLocalMethod(someData) {
    this.updateBarData()
    this.someStoreCall(someData)
  }
}

Надеюсь, это поможет.

1 голос
/ 30 января 2020

Я бы предложил использовать шину событий для этого варианта использования:

  1. в вашем Foo компоненте LocalMethod, который вы излучаете (например, называется " FooChanged *) 1008 * ") на шине
  2. обработчик событий в компоненте Bar (подписанный на события" FooChanged") выполнит свою работу и затем выдаст другое событие (например, с именем " BarFinished ") на шине
  3. обработчик события в компоненте Foo (подписанный на событие " BarFinished ") продолжится с следующий шаг в вашем потоке

Примерно так:

eventBus. js

import Vue from "vue";
export default new Vue();

Foo. vue

import events from "eventBus";

export default
{
  created()
  {
    events.$on("BarFinished", this.onBarFinished);
  },
  beforeDestroy()
  {
    events.$off("BarFinished", this.onBarFinished);
  },
  methods:
  {
    LocalMethod()
    {
      ....
      events.$emit("FooChanged", param1, param2);
    },
    onBarFinished(param1)
    {
      ...
    }
  }
}

Бар. vue

import events from "eventBus";

export default
{
  created()
  {
    events.$on("FooChanged", this.onFooChanged);
  },
  beforeDestroy()
  {
    events.$off("FooChanged", this.onFooChanged);
  },
  methods:
  {
    onFooChanged(param1, param2)
    {
      ...
      events.$emit("BarFinished", param1);
    }
  }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...