Vue.js:当请求正在进行时,将加载栏添加到整个页面

cl25kdpy  于 2023-06-30  发布在  Vue.js
关注(0)|答案(2)|浏览(126)

在我的页面上,我有一个“编辑”按钮在我的页面上,当我点击它我可以编辑一些东西,然后保存或关闭不保存。
我想添加一个加载栏(就像页面正在加载)时,用户点击“保存”按钮显示结果。

我现在拥有的是:

用户点击“编辑”按钮,一些数据变成可编辑的,并且他得到“保存”和“关闭”按钮(其关闭而不保存),如果他点击“保存”按钮,页面将重新加载编辑的数据,并且显示通知消息“更新”(或者如果更新没有通过,则显示错误消息)。

我想要的:

当用户在编辑后点击“保存”按钮时,页面将显示一个加载栏(以显示正在加载数据)几秒钟(例如5秒,如果请求在那时完成,加载将结束,但如果请求尚未完成,则栏将继续加载,直到完成),然后再次显示所有数据和“更新”通知。
下面是一些与此相关的代码:

我的按钮:

<v-col cols="3">
              <v-btn
                v-if="editGroup"
                light
                class="mx-2"
                @click="editGroup = false"
              >
                <v-icon left>mdi-close</v-icon>
                Close
              </v-btn>
              <v-btn
                v-if="editGroup" 
                light 
                class="mx-2" 
                @click="clickSave"
                >
                <v-icon left>mdi-content-save</v-icon>
                Save
              </v-btn>
              <v-btn
                v-if="
                  canShowButton(['administrateur', 'configurateur']) &&
                  !editGroup
                "
                light
                class="mx-2"
                @click="editGroup = true"
              >
                <v-icon left>mdi-pencil</v-icon>
                Edit
              </v-btn>
            </v-col>

我的编辑功能:

async clickSave() {
  this.editGroup = false
  this.loading = true

  let uri = this.endpointPrefix + '/groups/' + this.groupid
  let dat = {
    name: this.groupDataEdited.name,
    description: this.groupDataEdited.description,
    idTariff: this.groupDataEdited.idTariff,
    idEvseToAdd: [],
  }
  await this.$axios.$put(uri, dat)
    .then(() => {
        this.$nuxt.$emit('show-notification', {
          text: 'updated',
          color: 'green',
        })
        this.loadData(this.groupid)
    })
    .catch((error) => {
      this.$nuxt.$emit('show-notification', {
        text:
          'could not be updated !' +
          error.response.data,
        color: 'red',
      })
    })
    .finally(() => (this.loading = false))              
  setTimeout(() => {
    this.loading = false        
  }, 5000);
},

至于进度条,我使用vuetify进度循环如下:

<v-progress-circular
    v-show="loading"
    indeterminate
    color="primary">
   </v-progress-circular>

但是我仍然没有弄清楚我应该把这个组件放在我的代码的什么地方,还没有把它显示在我的所有页面中,我试着把它放在按钮之前,但它根本不起作用(什么也没有发生),如果我把它放在按钮里面,它会永远加载。

yrdbyhpb

yrdbyhpb1#

这就是像pinia这样的国家管理的目的。如果你像这样建立一个pinia商店:

import { defineStore } from "pinia"

export enum PageState {
  LOADING,
  LOADED,
  ERROR
}

export const usePageStore = defineStore({
  state: () => ({
    pageState: PageState.LOADED
  }),
  getters: {},
  actions: {
    saveData(endpointPrefix, groupId, newData) {
      try {
        // Put all your URL building/data calling work here
      } catch (e) {
        throw new Error(e)
      }
    },
  },
})

然后,不用在vue脚本中完成所有的数据工作,只需完成这一部分:

pageStore = usePageStore()

async clickSave() {
  try {
    pageStore.pageState = PageState.LOADING
    const response = await pageStore.getData(this.endpointPrefix, this.groupId, dat)
    this.$nuxt.$emit('show-notification', {
          text: 'updated',
          color: 'green',
        })
    this.loadData(this.groupid)
    pageStore.pageState = PageState.LOADED
  } catch (e) {
    pageStore.pageState = PageState.ERROR
     this.$nuxt.$emit('show-notification', {
        text:
          'could not be updated !' +
          error.response.data,
        color: 'red',
      })
  }  
}

然后,您的主页面视图可以访问相同的商店,监视该变量,并根据您的需要进行更改。

ndh0cuux

ndh0cuux2#

最好的办法可能是放置一个覆盖层,它可以放置在根元素的最底部。
举一个粗略的例子:

<v-col cols="3">
          <v-btn
            v-if="editGroup"
            light
            class="mx-2"
            @click="editGroup = false"
          >
            <v-icon left>mdi-close</v-icon>
            Close
          </v-btn>
          <v-btn
            v-if="editGroup" 
            light 
            class="mx-2" 
            @click="clickSave"
            >
            <v-icon left>mdi-content-save</v-icon>
            Save
          </v-btn>
          <v-btn
            v-if="
              canShowButton(['administrateur', 'configurateur']) &&
              !editGroup
            "
            light
            class="mx-2"
            @click="editGroup = true"
          >
            <v-icon left>mdi-pencil</v-icon>
            Edit
          </v-btn>
          <--The overlay will not display when loading is false-->
          <v-overlay v-model="loading">
            <v-progress-circular
            indeterminate
            color="primary">
            </v-progress-circular> 
          </v-overlay>
        </v-col>

覆盖将覆盖整个屏幕,直到加载 prop 被标记为假
https://vuetifyjs.com/en/components/overlays/
编辑:
此外,当您第一次加载时,必须在页面的数据部分设置加载。

<script>
  export default {
    data: () => ({
      loading: false,
    }),
    },
  }
</script>

相关问题