【问题标题】:How to watch only after the initial load from API in VueJS?如何仅在 VueJS 中的 API 初始加载后观看?
【发布时间】:2021-11-08 07:08:21
【问题描述】:

我从 API 获取数据,我用这些数据在我的组件中填充表单。我只需要在初始填充数据后触发观察者。就像以异步方式一样。但是观察者会立即被触发。只有在初始填充数据后更改了任何值时,我才需要禁用更新按钮。

<template>
  <div id="app">
    <input type="text" v-model="user.userId" /> <br />
    <br />
    <input type="text" v-model="user.title" /> <br />
    <br />
    <button :disabled="isDisabled">Update</button>
  </div>
</template>

<script>
export default {
  name: "App",
  watch: {
    user: {
      handler(oldVal, newVal) {
        if (oldVal != newVal) {
          this.isLoaded = false;
        }
      },
      deep: true,
    },
  },
  computed: {
    isDisabled() {
      return this.isLoaded;
    },
  },
  async created() {
    await fetch("https://jsonplaceholder.typicode.com/todos/1")
      .then((response) => response.json())
      .then((json) => {
        this.user = json;
        this.isLoaded = true;
      });
  },
  data() {
    return {
      user: {
        userId: 0,
        id: 0,
        title: "",
        completed: false,
      },
      isLoaded: true,
    };
  },
};
</script>

我已经推荐了Vue, await for WatchAre watches asynchronous?Vue.js How to watcher before mounted() , can't get data from watch,但我无法关注。

这是一个预览:https://codesandbox.io/embed/great-euler-skd3v?fontsize=14&hidenavigation=1&theme=dark

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    问题的最简单答案:

    Q:如何在VueJS中从API初始化加载后才观看?

    答:在watch 中添加标志(例如isLoaded)。

    您的代码也有一些问题:

    • async/await in created 什么都不做,
    • 不需要isDisabled,因为它仅基于来自data 的1 个值。您可以改用此值 (isLoading)。
    • 如果您的 api 调用失败,isLoading 标志将不会改变,更好的方法是将其移至 finally

    您的问题的解决方案(codesandbox):

    <template>
      <div id="app">
        <div v-if="!isFetching">
          <input type="text" v-model="user.userId" /> <br />
          <br />
          <input type="text" v-model="user.title" /> <br />
          <br />
          <button :disabled="!isLoaded">Update</button>
        </div>
        <div v-else>Loading...</div>
      </div>
    </template>
    
    <script>
    export default {
      name: "App",
      data() {
        return {
          user: {
            userId: 0,
            id: 0,
            title: "",
            completed: false,
          },
          isFetching: false,
          isLoaded: false
        };
      },
      watch: {
        user: {
          handler(oldVal, newVal) {
            if (!this.isFetching) {
              // this comparision doesn't work (cause oldVal/newVal is an object)
              if (oldVal != newVal) {
                this.isLoaded = false;
              }
            }
          },
          deep: true
        },
      },
      created() {
        this.isFetching = true;
        fetch("https://jsonplaceholder.typicode.com/todos/1")
          .then((response) => response.json())
          .then((json) => {
            this.user = json;
            this.isLoaded = true;
          })
          .finally(() => this.isFetching = false)
      },
    };
    </script>
    

    【讨论】:

    • 嗨。感谢您的尝试。即使在这种情况下,禁用按钮也始终处于禁用状态。请检查代码和框链接。我复制粘贴了你的答案
    • @GrandWhiz 请再检查一次,它对我来说很好用。请注意,您在手表内的比较将不起作用,因为您正在使用相等运算符比较对象。除非有什么误解。删除 if (oldVal != newVal) 并按预期工作。
    • 嗨。非常感谢。但是,你能分享一个工作的密码箱或密码笔吗?更新按钮要么始终启用,要么始终禁用:((我什至将这个答案复制粘贴到我的代码框中)
    • @GrandWhiz 添加了代码框。请记住有关比较的评论,您应该删除此条件或将其替换为工作对象比较方法。
    【解决方案2】:

    这需要通过一些条件来确定。

    isLoaded 已经用于确定初始加载的状态,但名称令人困惑,因为它确定数据加载。

    可以是:

      watch: {
        user: {
          if (this.isLoading && oldVal != newVal) {
            this.isLoading = false;
          }
          ...
    

    观察者不需要是deep,并且在不需要时可以不被观察:

    async created() {
      let unwatchUser = this.$watch('user', (oldVal, newVal) => {
        if (this.isLoading && oldVal != newVal) {
          this.isLoading = false;
          unwatchUser();
        }
      })
      ...
    

    指定尚未加载数据的常用方法是将其设置为null,即没有值。这不需要isLoading 标志或观察者。如果 null 由于引用的对象属性而不受欢迎,则可以通过可选的链接和条件渲染来克服:

      <div v-if="user">
          <input type="text" v-model="user.userId" />
          ...
      <div v-else class="spinner"/>
    

    【讨论】:

    • 您好,感谢您的回复。如果你不介意,你能给出完整的结构吗?你提到了两次观察者,所以我无法关注
    • 我添加了一些上下文。您需要在 watchcreated 中有一个观察者,而不是两者。
    • 仍然面临同样的问题。我附上了codeandbox链接。请检查更新按钮是否始终处于禁用状态
    • 这里isLoaded的目的是什么?您已经拥有反映数据加载状态的 isFetching。
    猜你喜欢
    • 2017-09-24
    • 2013-01-08
    • 2018-04-18
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    相关资源
    最近更新 更多