VueJS等待所有API查询返回

huangapple go评论81阅读模式
英文:

VueJS Wait for all API queries to come back

问题

早上好,

我有一个使用Django Rest Framework编写的API。前端是用VueJS编写的。我有一个表单视图,可以是“新增”或“修改”。基本上,表单是相同的代码,但会检查路径是否包含ID(因此是修改)。

要修改条目,需要进行一系列API调用以获取下拉菜单/选择菜单中的各种选项。这些选项在模型上是一对一的外键(例如,演员有一个类别),还有一些是模型上的多对多键(例如,演员有一个或多个动机)。

我目前遇到的主要问题是,每个选项(总共有十四个)都有一个API调用。在我看来,这些选项会返回并在所有API调用完成之前呈现。过去,我只是使用了一个布尔值来进行“加载”以执行v-if语句。

由于有这么多选项,我有一个布尔值列表,嵌套在v-if中:

<b-container v-if="load_list.every((x) => x)">

然后我尝试使用一个计算值:

<b-container v-if="listLoaded">

在计算值中:

computed: {
    listLoaded: function() {
        return this.load_list.every((x) => x)
    }
}

所有的值都会在API调用返回后调整,并且列表变为全部为false,但容器不会改变。

以下是从Vue的created生命周期中调用的示例API调用,该生命周期调用一个使用axios调用DRF端点的函数(数据返回正常):

created: function() {
    API.getActor(this.id)
        .then(a => {
            this.getActor(a)
        })
        .catch(error => console.log(error))
        .finally(() => {
            this.load_list[0] = false
        })
}

我如何确保在视图渲染之前所有的API都返回了?我确信有更好的方法可以做到这一点(除了它不起作用...),但是我在研究中没有完全理解。

感谢您的帮助。

BCBB

英文:

Good morning,

I have an API written in Django Rest Framework. The front end is written in VueJS. I have a form view that is either an Add New or a Modify. Basically, the form is the same code, but checks to see if the path includes an ID (and thus, is a modify).

To modify the entry, there are a series of API calls for all the various options in dropdown / select menus. These are one-to-one foreign keys on the model (i.e. an actor has a category) and a couple that are many-to-many keys on the model (i.e. actor has one or more motivations).

My big issues right now is that each of these options (there are fourteen total) has an API call. It seems to me that the options are returning and then rendering without all of API calls finished. In the past, I have just used a boolean value for "loading" to do a v-if statement.

With so many, I had a list of boolean values and embedded within the v-if:

&lt;b-container v-if=&quot;load_list.every((x) =&gt; x)&quot;&gt;


data () {
    return {
           load_list: [true, true, true, true, true, true, true, true, true],

Then I tried with a computed value:

&lt;b-container v-if=&quot;listLoaded&quot;&gt;

computed: {
    listLoaded: function() {
      return this.load_list.every((x) =&gt; x)
    }

All of the values get adjusted on the returns of the API calls and the list becomes all false, but the container isn't changing.

Example API call that is called from the Vue created, which calls a function that makes the call to the DRF endpoint with axios (data returns just fine):

created: function() {
      API.getActor(this.id)
        .then(a =&gt; {
          this.getActor(a)
        })
        .catch(error=&gt; console.log(error))
        .finally(() =&gt; {
          this.load_list[0] = false
        })

How can I make sure all my of my API return prior to the view rendering? I am sure there is a better way to do it (besides just it not working...), but I am not grasping it in my research.

Thanks for your help.

BCBB

答案1

得分: 0

你应该使用一个 watcher,而不是使用 computed 属性,它将完全适合你的情况:

Watcher 官方文档

在你的情况下,你可以监视你的 load_list 数据属性。每当 load_list 中发生任何变化时,该 watcher 将运行。在 watcher 中,通过比较你的值组合,你可以设置你的 listLoaded(你应该在 data() 中声明)。

你的场景示例 watcher 代码
watch: {
   //每当 load_list 改变时,该函数将运行

   load_list: {
    handler(newList, oldList) {
      let isLoaded = newList.every((x) => x)

      if (isLoaded) {
        //在这里编写代码
      }
    }
   }
 },

我希望这对你有所帮助。

英文:

You should use a watcher instead of using computed property it will perfectly fit in you scenario:

Watcher official docs

In your case you can watch your load_list data property. when whenever any change happen in load_list then that watcher will run.In the watcher by comparing your values combinations you can set your listLoaded (which you should need to declare within the data())

Example watcher code of your scenario

watch:{
   //whenever load_list changes, this function will run

   load_list:{
    handler(newList, oldList) {
      let isLoaded= newList.every((x) =&gt; x)

      if(isLoaded){
        //code here 
      },
    }
   }
 },

I hope that will help you.

答案2

得分: 0

&lt;!-- 开始代码段: js 隐藏: false 控制台: true Babel: false --&gt;

&lt;!-- 语言: lang-js --&gt;

const vm = new Vue({
  el: &quot;#root&quot;,
  data() {
    return {
      list1: [false, true],
      list2: {
        0: false,
        1: true
      }
    }
  },
  computed: {
    load1() {
      return this.list1.every(it =&gt; it);
    },
    load2() {
      return Object.values(this.list2).every(it =&gt; it);
    }
  },
  methods: {
    handler1() {
      Vue.set(this.list1, 0, true);
    },
    handler2() {
      this.list2[0] = true;
    }
  }
});

&lt;!-- 语言: lang-html --&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;
  &lt;div&gt;
    &lt;div&gt;
      &lt;div v-if=&quot;load1&quot;&gt;All true&lt;/div&gt;
      &lt;button type=&quot;button&quot; @click=&quot;handler1&quot;&gt;Array&lt;/button&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;div v-if=&quot;load2&quot;&gt;All true&lt;/div&gt;
      &lt;button type=&quot;button&quot; @click=&quot;handler2&quot;&gt;Object&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;!-- 结束代码段 --&gt;

由于 JavaScript 的限制,Vue 无法检测数组和对象的某些类型的更改。这些在响应性部分讨论。

[查看](https://v2.vuejs.org/v2/guide/list.html#Caveats)
英文:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const vm = new Vue({
  el: &quot;#root&quot;,
  data() {
    return {
      list1: [false, true],
      list2: {
        0: false,
        1: true
      }
    }
  },
  computed: {
    load1() {
      return this.list1.every(it =&gt; it);
    },
    load2() {
      return Object.values(this.list2).every(it =&gt; it);
    }
  },
  methods: {
    handler1() {
      Vue.set(this.list1, 0, true);
    },
    handler2() {
      this.list2[0] = true;
    }
  }
});

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;
  &lt;div&gt;
    &lt;div&gt;
      &lt;div v-if=&quot;load1&quot;&gt;All true&lt;/div&gt;
      &lt;button type=&quot;button&quot; @click=&quot;handler1&quot;&gt;Array&lt;/button&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;div v-if=&quot;load2&quot;&gt;All true&lt;/div&gt;
      &lt;button type=&quot;button&quot; @click=&quot;handler2&quot;&gt;Object&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

Due to limitations in JavaScript, there are types of changes that Vue cannot detect with arrays and objects. These are discussed in the reactivity section.

See

答案3

得分: 0

关于USD组件键

<b-container v-if="load_list.every((x) => x)" :key="componentKey">

function() {
     API.getActor(this.id)
       .then(a => {
         this.getActor(a)
         this.componentKey++
       })
       .catch(error=> console.log(error))
       .finally(() => {
         this.load_list[0] = false

       })
英文:

how about usd componentkey

&lt;b-container v-if=&quot;load_list.every((x) =&gt; x)&quot; :key=&quot;componentKey&quot;&gt;

 function() {
      API.getActor(this.id)
        .then(a =&gt; {
          this.getActor(a)
          this.componentKey++
        })
        .catch(error=&gt; console.log(error))
        .finally(() =&gt; {
          this.load_list[0] = false

        })

huangapple
  • 本文由 发表于 2023年7月27日 21:04:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定