Компонент Vue.js не передает родительский объект после успешного вызова axios - PullRequest
2 голосов
/ 18 октября 2019

Я использую

"axios": "^0.19.0",
"vue": "^2.6.10",
"vuex": "^3.1.1"

Мое действие vuex выглядит следующим образом и вызывает удаленный интерфейс, используя axios. Запрос работает и получает действительный ответ.

skipQuestion({commit}, payload) {
    let params = {
        answer: {
            id: payload.id,
            skipped: true,
        }
    };

    return new Promise((resolve, reject) => {
        commit(UPDATE_LOADING, true);
        Remote.put(`/answer.json`, params)
            .then((response) => {
                commit(UPDATE_LOADING, false);
                commit(SKIP_QUESTION, payload.id);
                resolve();
            })
            .catch((error) => {
                commit(UPDATE_LOADING, false);
                reject(error);
            })
    })
},

Компонент Question имеет следующий метод skip, который вызывает действие vuex skipQuestion и должен выдавать skip событие для родительского компонента.

...mapActions(['skipQuestion']),
skip(evt) {
    let payload = { id: this.question_id };
    this.skipQuestion(payload).then( () => {
        this.$emit('skip', this.uuid);
    }).catch( (error) => {
        console.log(error);
    });
},

Проблема в том, что событие skip не отправляется родителю при его использовании в блоке then действия. Консоль разработчика vue для chrome также подтверждает, что событие skip было запущено. Если я поставлю Emit за пределами блока, все работает. Любые предложения, что идет не так?

Редактировать 1

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

skip(evt) {
    let payload = { id: this.question_id };
    let vm = this; 
    this.skipQuestion(payload).then( () => {
        console.log('before skip emit');
        vm.$emit('skip', this.uuid);
        console.log('after skip emit');
    }).catch( (error) => {
        console.log(error);
    });
},

Редактировать 2

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

<question v-bind="question"
          :key="question.uuid"
          v-if="questionReady"
          v-on:skip="onSkipQuestion"
          v-on:answer="onAnswerQuestion">
</question>

Как было сказано ранее, если не использовать блок Promise / then-block, возвращенный запросом axios, emit выполняетработай. Ниже вы найдете метод, который должен называться:

methods: {
  onSkipQuestion(payload) {
    // this code is not executed
    console.log('onSkipQuestion')

    //....
  },


  //....
}      

Ответы [ 3 ]

1 голос
/ 22 октября 2019

Возможно, проблема в том, что вы не возвращаете resol () или reject () в skipQuestion ().

В любом случае, если ваше приложение использует ES2017 (или выше), или, если нет, то Babel , я бы уточнил функцию, чтобы использовать структуру async / await, чтобы this не будет подвергаться никакому риску (имеется в виду ответ Варуна ) и не подвергается никакому риску, если skipQuestion() ничего не возвращает, как в настоящее время:

async skip(evt) {
    let payload = { id: this.question_id };
    try {
      let result = await skipQuestion(payload)
      this.$emit('skip', this.uuid);
    } catch(error){
      console.log(error);
    }
}

Не возвращается resolve / reject - известный источник ошибок в случае синтаксиса Promise((resolve, reject) => {...})

0 голосов
/ 26 октября 2019

Суммируйте вашу информацию, указанную:

Консоль разработчика vue для chrome также подтверждает, что событие пропуска было запущено.


TL; DR

  • vm.$emit в основном вызывает каждый метод, указанный в vm._events[eventName]

  • v-on, регистрируется через context.listeners increateElemet и вводится через updateListeners


В основном вы можете отлаживать с помощью оператора debugger:

skip(evt) {
    let payload = { id: this.question_id };
    this.skipQuestion(payload).then( () => {
        debugger; // scope -> _events & scope -> $parent.componentInstance
        // or console.log(JSON.stringify(this._events))
        this.$emit('skip', this.uuid);
    }).catch( (error) => {
        console.log(error);
    });
},

Тогда вы знаете, что происходит.


Что нужно проверить:

  • Действителен this Область действия

  • действительно parent

  • фактически сработало в соответствии с разрешением

  • vm._events зарегистрировано

0 голосов
/ 18 октября 2019

Вы потеряли ссылку на this внутри блока then. Ссылка теперь называется функцией обратного вызова. Вместо этого сделайте это

 ...mapActions(['skipQuestion']),
    skip(evt) {
        let payload = { id: this.question_id };
        let vm = this; // Preserve Vue instance for use inside block
        this.skipQuestion(payload).then( () => {
            vm.$emit('skip', vm.uuid);
        }).catch( (error) => {
            console.log(error);
        });
    },
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...