在渲染组件之前从 api 获取数据

新手上路,请多包涵

我在渲染页面之前发送了 2 个 api 请求:

 const Profile = {
    template: '#profile',
    attributes: null,
    photos: [],
    data: function () {
        return {attributes: Profile.attributes, photos: Profile.photos};
    },
    beforeRouteEnter: function (to, from, next) {
        function getProfile() {
            return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
        }
        function getPhotos() {
            return axios.get('photos?access-token=1', {responseType: 'json'});
        }

        axios.all([getProfile(), getPhotos()])
            .then(axios.spread(function (profile, photos ) {
                console.log(profile, photos );
                next(vm => {
                    vm.setProfile(profile);
                    vm.setPhotos(photos);
                })
            }));
    },
    methods: {
        setProfile: function (response) {
            Profile.attributes = response.data;
            console.log(Profile.attributes);
        },
        setPhotos: function (response) {
            Profile.photos = response.data;
            console.log(response);
        },
    }
};

问题是渲染发生在 setProfilesetPhotos 方法之前。如何正确渲染我的组件?

原文由 Alex 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 770
2 个回答

正如评论中提到的,第一个 async/await 解决方案有点误导,因为所有生命周期方法都是 synchronous 。这是可行的,因为代码被转换为内部带有 IIFE 的同步函数。

下面我添加了一些最近的片段。

旧答案

用 async/await 试试。我删除了 beforeRouteEnteraxios.spread 并添加了 create

 const Profile = {
  template: '#profile',
  attributes: null,
  photos: [],
  data() {
    return {
      attributes: null,
      photos: null,
    };
  },
  async created() {
    const getProfile = await axios.get('user/get-profile?access-token=1');
    const getPhotos = await axios.get('photos?access-token=1');

    this.setProfile(profile);
    this.setPhotos(photos);
  },
  methods: {
    setProfile(response) {
      this.attributes = response.data;
      console.log(this.attributes);
    },
    setPhotos(response) {
      this.photos = response.data;
      console.log(response);
    },
  },
};

更短

const Profile = {
  template: '#profile',
  attributes: null,
  photos: [],
  data() {
    return {
      attributes: null,
      photos: null,
    };
  },
  async created() {
    this.attributes = await axios.get('user/get-profile?access-token=1');
    this.photo = await axios.get('photos?access-token=1');
  },
};

更新的答案

您可以在生命周期方法中使用异步函数。

 const Profile = {
  template: '#profile',
  attributes: null,
  photos: [],
  data() {
    return {
      attributes: null,
      photos: null,
    };
  },
  created() {
    const fetchData = async () => {
      const { data: attributes } = await axios.get(
        'user/get-profile?access-token=1'
      );
      const { data: photos } = await axios.get('photos?access-token=1');

      this.attributes = attributes;
      this.photos = photos;
    };

    fetchData();
  },
};

Vue 3和 setup()

在 Vue 3 中,您可以使用 async setup() 。如果你使用它,你必须用 Suspense 包装你的组件。警告!这个 API 目前是 实验性https://vuejs.org/guide/built-ins/suspense.html#suspense=

 <Suspense>
  <template #default>
    <YourComponent />
  </template>
  <template #fallback>
    <div>Loading ...</div>
  </template>
</Suspense>

 export default {
  name: 'YourComponent',
  async setup() {
    const { data: attributes } = await axios.get('user/get-profile?access-token=1');
    const { data: photos } = await axios.get('photos?access-token=1');

    return {
      attributes,
      photos
    }
  }
}

原文由 Philip 发布,翻译遵循 CC BY-SA 4.0 许可协议

您应该能够返回从调用 axios.all 返回的 Promise,例如:

 return axios.all([getProfile(), getPhotos()])
// .then() => ...

或者您可以向数据对象添加一个属性并使用它来显示加载器,直到所有 Promises 都已解决

const Profile = {
    template: '#profile',
    attributes: null,
    photos: [],
    data: function () {
        return {attributes: Profile.attributes, photos: Profile.photos, isLoading: true};
    },
    beforeRouteEnter: function (to, from, next) {
        function getProfile() {
            return axios.get('user/get-profile?access-token=1', {responseType: 'json'});
        }
        function getPhotos() {
            return axios.get('photos?access-token=1', {responseType: 'json'});
        }

        axios.all([getProfile(), getPhotos()])
            .then(axios.spread(function (profile, memes) {
                console.log(profile, memes);
                this.isLoading = false

                next(vm => {
                    vm.setProfile(profile);
                    vm.setPhotos(photos);
                })
            }));
    },
    methods: {
        setProfile: function (response) {
            Profile.attributes = response.data;
            console.log(Profile.attributes);
        },
        setPhotos: function (response) {
            Profile.photos = response.data;
            console.log(response);
        },
    }
};

模板代码省略,但您可以根据 isLoading 切换您显示的内容。如果你沿着这条路线走,那么最好为加载器创建一个抽象。

我还建议您可能想查看 vuex 而不是将所有数据耦合到任何特定的组件状态。

原文由 Purple Hexagon 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题