bluezhan / vue2

【🔥Vue.js资讯📚】目前web前端开发非常火爆的框架;定时更新,欢迎 Star 一下。
https://itemsets.github.io/vue2
MIT License
444 stars 117 forks source link

Vue.js应用的四种AJAX请求数据模式 #13

Open bluezhan opened 7 years ago

bluezhan commented 7 years ago

Vue.js应用的四种AJAX请求数据模式

翻译原文出处:4 AJAX Patterns For Vue.js Apps
脾人翻译略差,别见笑。

如果您闲的没事干去两个Vue.js开发人员:“在Vue应用中使用AJAX的正确姿势是咋样的?”,您将会得到三种或更多的不同回答。

Vue.js官方没有提供实现AJAX的指定方式,并且有许多不同的设计模式可以被有效地使用。每个都有自己的利弊,应根据要求进行判断。你甚至可以同时使用几个!

在本文中,我将向您展示您可以在Vue应用程序中实现AJAX的四个位置:

1、根实例 2、组件Components 3、Vuex actions 4、路线导航卫士 5、[另加:奖金模式]()

我将解释每个方法,举一个例子,并涵盖利弊。

一、根实例

在使用Vue框架时,您可以一开始就从根实例发出所有AJAX请求,即写好所有的数据请求,并将所有状态存储在该实例中。如果任何子组件需要数据,它将会顺着props中传下来。如果子组件需要刷新数据,则将使用自定义事件来提示根实例请求它。


new Vue({
  data: {
    message: ''
  },
  methods: {
    refreshMessage(resource) {
      this.$http.get('/message').then((response) {
        this.message = response.data.message;
      });
    }
  }
})

Vue.component('sub-component', {
  template: '<div>{{ message }}</div>',
  props: [ 'message' ]
  methods: {
    refreshMessage() {
      this.$emit('refreshMessage');
    }
  }
});

优点

缺点

随着您的应用扩展,需要书写大量的“props”和自定义事件。

二、组件Components

在使用Vue框架时,组件负责管理自己的AJAX请求和独立状态。实际上,您可能需要创建几个“容器组件”来管理本地组“展示组件”的数据。

例如,filter-list可能是一个容器组件包装filter-input和filter-reset,它们作为展示组件。filter-list将包含AJAX数据逻辑,并且将管理该组中所有组件的数据,通过props和事件进行通信。

请参阅译文《容器组件和展示组件》原作者:Dan Abramov,可以更好地深入了解这种模式。

为了简化此架构的实现,您可以将任何AJAX逻辑抽象为混合,然后在组件中使用mixin使其成为AJAX。


let mixin = {
  methods: {
    callAJAX(resource) {
      //...
    }
  }
};

Vue.component('container-comp', {
  // No meaningful template, I just manage data for my children
  template: '<div><presentation-comp :mydata="mydata"></presentation-comp></div>', 
  mixins: [ myMixin ],
  data() {
    return {
     //... 
    }
  },

});

Vue.component('presentation-comp', {
  template: '<div>I just show stuff like {{ mydata }}</div>',
  props: [ 'mydata' ]
});

优点

缺点

三、Vuex actions

在使用Vue框架时,您可以在Vuex store中管理状态和AJAX逻辑; 组件可以通过dispatch方法操作来请求新数据(store.dispatch将用于触发actions动作)。

如果您要使用此模式,最好从您的action中返回一个promise,以便对AJAX请求的解析做出反应,例如隐藏加载微调器,重新启用按钮等。


store = new Vuex.Store({
  state: {
    message: ''
  },
  mutations: {
    updateMessage(state, payload) {
      state.message = payload
    }
  },
  actions: {
    refreshMessage(context) {
      return new Promise((resolve) => {
        this.$http.get('...').then((response) => {
          context.commit('updateMessage', response.data.message);
          resolve();
        });
      });
    }
  }
});

Vue.component('my-component', {
  template: '<div>{{ message }}</div>',
  methods: {
    refreshMessage() {
      this.$store.dispatch('refeshMessage').then(() => {
        // do stuff
      });
    }
  },
  computed: {
    message: { return this.$store.state.message; }
  }
});

本人比较喜欢这种数据请求模式,因为它很好地分离了你的状态和表现的逻辑。如果你正在使用Vuex,这是要走的路。如果你不使用Vuex,这模式可能是一个很好的理由。

优点

缺点

四、路线导航卫士

在使用Vue框架时,您的应用程序分为多个页面,当路由更变时,将抓取页面及其子组件所需的所有数据。

这种方法的主要优点是它真正简化了您的UI。如果组件独立获取自己的数据,则当组件数据以任意顺序填充时,页面将不可预测地重新呈现。

实现这一点的一个整洁的方法是在您的服务器上为每个页面创建端点,例如/about,/contact与您的应用程序中的路由名称相匹配。然后,您可以实现一个通用beforeRouteEnter钩子,将所有数据属性合并到页面组件的数据中:


import axios from 'axios';

router.beforeRouteEnter((to, from, next) => {
  axios.get(`/api${to.path}`).then(({ data }) => {
    next(vm => Object.assign(vm.$data, data))
  });
})

优点

缺点

奖金模式:将第一个AJAX调用的服务器渲染到页面中

建议在初始页面加载时使用AJAX来检索应用程序状态,因为它需要额外的往返服务器,这将延迟应用程序的渲染。

相反,将初始应用程序状态注入HTML页面的内联脚本中,以便应用程序作为全局变量在需要时可用。

<html>
...
<head>
  ...
  <script type="text/javascript">
   window.__INITIAL_STATE__ = '{ "data": [ ... ] }';
  </script>
</head>
<body>
  <div id="app"></div>
</body>
</html>

然后,AJAX可以更适合地用于后续数据提取。

如果您有兴趣了解有关此架构的更多信息,请参阅作者的文章“避免此全面堆栈Vue / Laravel应用程序中的常见反模式”。

FuDesign2008 commented 6 years ago

很赞的文章 👍

lei123zhang commented 6 years ago

very good

zipeijun commented 6 years ago

我考虑过使用 Vuex 的方式管理请求、但是每个页面并不是只有一个请求。随着项目的扩大、Vuex 本身维护起来也很复杂、且 active 是全局的、那也就是说到项目后期、Vuex 本身也会变的非常臃肿。想听听作者更详细的想法。

bluezhan commented 5 years ago

我考虑过使用 Vuex 的方式管理请求、但是每个页面并不是只有一个请求。随着项目的扩大、Vuex 本身维护起来也很复杂、且 active 是全局的、那也就是说到项目后期、Vuex 本身也会变的非常臃肿。想听听作者更详细的想法。

 暂没什么其它想法,我们目前是单独抽离API层出来处理的。

FuDesign2008 commented 5 years ago

@zipeijun vuex 本身臃肿指什么呢?是指vuex 的文件会变得很大么? 如果是这样的话可以拆分,比如一个页面对应一个vuex module,参见 https://vuex.vuejs.org/guide/modules.html

zipeijun commented 5 years ago

@FuDesign2008 这里臃肿指的是 Vuex 的 Getters、Getters 本身是全局的、即使使用 module、拆分的仅仅是代码。 所以我认为 api 还是不适合使用 Vuex 来进行管理、单独抽离 api 层来进行管理和转换来的好一些。

FuDesign2008 commented 2 years ago

@FuDesign2008 这里臃肿指的是 Vuex 的 Getters、Getters 本身是全局的、即使使用 module、拆分的仅仅是代码。 所以我认为 api 还是不适合使用 Vuex 来进行管理、单独抽离 api 层来进行管理和转换来的好一些。

好久没有看这个 issue, 发现参与的工程已经走在单独的API层路上。

826386366 commented 2 years ago

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。