状态更新后UI不反应不重新渲染

问题描述 投票:0回答:1

我构建了以下简单的UI。

screenshot of UI

在点击垃圾桶图标时,由于状态改变,书签应该被删除,UI也会更新。API调用已经完成,我可以在开发工具中看到该动作的发生。然而,我必须合并该动作,或者导航离开页面,或者进行硬重载,才能使删除的书签不显示出来。我希望通过使用vuex的mapState helper来解决这个问题。

以下是相关部分。

view(抱歉,这个有点乱)--这其实是未删减的版本。

<template>
  <div>
    <v-card class="mx-auto" max-width="700">
      <v-list two-line subheader>
        <v-subheader>Bookmarks</v-subheader>
        <v-list-item
          v-for="obj in Object.entries(bookmarks).sort((a, b) => {
            return a[1].paragraph - b[1].paragraph;
          })"
          :key="obj[0]"
        >
          <v-list-item-avatar>
            <v-icon @click="goTo(obj)">mdi-bookmark</v-icon>
          </v-list-item-avatar>
          <v-list-item-content @click="goTo(obj)">
            <v-list-item-title>
              {{ obj[0].split('/')[1] + ' by ' + obj[0].split('/')[0] }}
            </v-list-item-title>
            <v-list-item-subtitle>
              Part {{ obj[1].part + 1 }}, paragraph {{ obj[1].paragraph + 1 }}
            </v-list-item-subtitle>
          </v-list-item-content>
          <v-list-item-action>
            <v-btn icon>
              <v-icon @click="deleteBookmark(obj[0])" title="Remove bookmark"
                >mdi-delete</v-icon
              >
            </v-btn>
          </v-list-item-action>
        </v-list-item>
      </v-list>
    </v-card>
  </div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  computed: {
    ...mapState(['bookmarks'])
  },
  methods: {
    ...mapActions(['deleteBookmark']),
    goTo(obj) {
      const [authorName, title] = obj[0].split('/');
      this.$router.push({
        name: 'showText',
        params: {
          authorName,
          title
        },
        query: { part: obj[1].part, paragraph: obj[1].paragraph }
      });
    }
  }
};
</script>

store:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

import apiService from '@/services/ApiService';

const store = new Vuex.Store({
  state: {
    bookmarks: {}
  },
  mutations: {
    SET_BOOKMARKS(state, bookmarks) {
      state.bookmarks = bookmarks;
    }
  },
  actions: {
    async deleteBookmark({ commit, state }, key) {
      let { bookmarks } = state;
      const response = await apiService.deleteBookmark(key);
      delete bookmarks[key];
      commit('SET_BOOKMARKS', bookmarks);
      return response;
    }
  }
});

export default store;

apiService。

import axios from 'axios';

const apiClient = axios.create({
  baseURL: process.env.VUE_APP_API_URL,
  withCredentials: true,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
  responseType: 'json'
});

export default {
  deleteBookmark(key) {
    return apiClient.delete(`/api/bookmarks/${key}`);
  }
};
vue.js vuex vuetify.js
1个回答
2
投票

红旗就在这里。

delete bookmarks[key];

请阅读 变化检测注意事项.

使用 Vue.delete 而不是。

Vue.delete(bookmarks, key);

Doing commit('SET_BOOKMARKS', bookmarks); 后,不会导致任何变化发生,因为你只是在分配同一个对象实例。最好的办法是写一个 REMOVE_BOOKMARK 突变来处理这个问题,所以你不会在突变之外改变Vuex的状态。

© www.soinside.com 2019 - 2024. All rights reserved.