VueJs 中全局加载的数据偶尔为空

Global loaded data in VueJs is occasionally null

我是 VueJs 的新手,目前正在尝试仅加载一次数据并使其对所有 vue 组件全局可用。实现这一目标的最佳方法是什么? 我有点卡住了,因为全局变量有时似乎变成了 null,我不知道为什么。

在我的 main.js 中,我制作了三个全局 Vue 实例变量:

let globalData = new Vue({
  data: {
    $serviceDiscoveryUrl: 'http://localhost:40000/api/v1',
    $serviceCollection: null,
    $clientConfiguration: null
  }
});
Vue.mixin({
  computed: {
    $serviceDiscoveryUrl: {
      get: function () { return globalData.$data.$serviceDiscoveryUrl },
      set: function (newUrl) { globalData.$data.$serviceDiscoveryUrl = newUrl; }
    },
    $serviceCollection: {
      get: function () { return globalData.$data.$serviceCollection },
      set: function (newCollection) { globalData.$data.$serviceCollection = newCollection; }
    },
    $clientConfiguration: {
      get: function () { return globalData.$data.$clientConfiguration },
      set: function (newConfiguration) { globalData.$data.$clientConfiguration = newConfiguration; }
    }
  }
})

并在我的 App.vue 组件中加载所有数据:

<script>
  export default {
    name: 'app',
    data: function () {
      return {
        isLoading: true,
        isError: false
      };
    },
    methods: {
      loadAllData: function () {
        this.$axios.get(this.$serviceDiscoveryUrl)
          .then(
            response => {
              this.$serviceCollection = response.data;

              let configurationService = this.$serviceCollection.services.find(obj => obj.key == "ProcessConfigurationService");

              this.$axios.get(configurationService.address + "/api/v1/clientConfiguration").then(
                response2 => {
                  this.$clientConfiguration = response2.data;
                }
              );
              this.isLoading = false;
            })
      }
    },
    created: function m() {
      this.loadAllData();
    }
  }
</script>

但是当我尝试访问 $clientConfiguration 时,它似乎不时出现 null,我不明白为什么。例如,当我尝试构建导航侧边栏时:

    beforeMount: function () {
      let $ = JQuery;
      let clients = [];
      if (this.$clientConfiguration === null)
        console.error("client config is <null>");

      $.each(this.$clientConfiguration, function (key, clientValue) {
        let processes = [];
        $.each(clientValue.processConfigurations, function (k, processValue) {
          processes.push(
            {
              name: processValue.name,
              url: '/process/' + processValue.id,
              icon: 'fal fa-project-diagram'
            });
        });

        clients.push(
          {
            name: clientValue.name,
            url: '/client/' + clientValue.id,
            icon: 'fal fa-building',
            children: processes
          });
      });

      this.nav.find(obj => obj.name == 'Processes').children = clients;

最可能的原因是null只是初始值。加载数据是异步的,因此您需要等待加载完成,然后再尝试创建任何依赖该数据的组件。

你有一个 isLoading 标志,我猜这是你试图在显示任何组件之前等待加载完成(可能通过合适的 v-if)。但是,它目前只等待第一个请求而不是第二个。所以这个:

this.$axios.get(configurationService.address + "/api/v1/clientConfiguration").then(
  response2 => {
    this.$clientConfiguration = response2.data;
  }
);
this.isLoading = false;

需要:

this.$axios.get(configurationService.address + "/api/v1/clientConfiguration").then(
  response2 => {
    this.$clientConfiguration = response2.data;
    this.isLoading = false;
  }
);

如果问题不是初始值,那么您需要弄清楚是什么将其设置为 null。这应该很简单,只需在 setter:

中添加 debugger 语句
$clientConfiguration: {
  get: function () { return globalData.$data.$clientConfiguration },
  set: function (newConfiguration) {
    if (!newConfiguration) {
      debugger;
    }
    globalData.$data.$clientConfiguration = newConfiguration;
  }
}

除了 null 的问题之外,如果您使用的是 Vue 2.6+,我建议您看一下 Vue.observable,这是一种比创建反应对象更简单的创建反应对象的方法新的 Vue 实例。

就我个人而言,我可能会通过在 Vue.prototype 上放置一个反应对象而不是使用全局混合来实现所有这些。这假设你甚至需要对象是反应性的,如果你不这样做,那么这一切都比它需要的要复杂一些。