【问题标题】:VueX: how to load the data of a foreign key (microservice architecture)VueX:如何加载外键的数据(微服务架构)
【发布时间】:2021-04-13 12:59:13
【问题描述】:

在我的项目中,我有状态 productsorders。每个订单都包含一个产品的 ID,或者一个带有产品 ID 的数组。它们来自不同的 API。 (如微服务架构)

订单的 JSON 结构:

[
   {
      "orderId": 1,
      "productId": 360
   }
]

order.js

export const state = () => ({
  order: {}
})

export const getters = {
  order: state => state.allOrder,
}

export const mutations = {
  async setOrderById(state, order) {
     state.order = order;
  }

export const actions = {
  async setOrderById(state, orderId) {
    const order = await this.$axios.get(api + orderId);
    state.commit('setOrderById', client.data);
  }

product.js 具有相同的结构,但具有一些不同的属性,例如“标题、名称、价格等:

{
  "id": 2,
  "title_de": "Example T-Shirt",
  "price": 550
}

现在,我想在我的组件中加载订单的产品属性。最好的做法是什么?这有点复杂,因为在我的组件中,我通过计算属性加载数据。最后,我想要这样的东西:

OrderComponent.vue

<template>
  <div v-if="currentOrder">
    {{ currentOrder.product.title }} <!-- UNDEFINED -->
    {{ currentOrder.product.price }} <!-- UNDEFINED -->
  </div>
</template>

<script>
import {mapGetters} from 'vuex';

export default {
  name: "OrderDetail",
  data() {
    return {
      orderId: this.$route.params.id,
    }
  },
  computed: {
    ...mapGetters({
      currentOrder: 'shop/orders/order'
    })
  },
  mounted() {
    this.$store.dispatch('shop/orders/setOrderById', this.orderId)
  }
}
</script>

正如我研究的那样,没有办法操纵计算的属性。当然这个例子是行不通的,因为在一个订单中只有productId。

【问题讨论】:

  • 这有点复杂,因为在我的组件中,我通过计算属性加载数据 - 计算属性 应该对如何获取订单数据一无所知,这应该是 Vuex 操作的工作。你为什么不在setOrderById 中获取产品?如果您的问题是关于如何构建状态,那么您应该为 orderAndProductDetails 设置单独的状态,并在视图中使用的那些属性 (currentOrder.product.price) 由操作填充。

标签: vue.js nuxt.js vuex computed-properties


【解决方案1】:

您想使用 beforeMount() 而不是mounted()。 Details Here

在挂载开始前调用:即将第一次调用渲染函数。

async beforeMount() {
   await this.$store.dispatch('shop/orders/setOrderById', this.$route.params.id);
}

【讨论】:

  • 谢谢,但这并不能真正回答我的问题。我的问题不清楚吗?
【解决方案2】:

如果您想通过最佳实践来实现这一点并使用干净的方式构建动态订单组件,请检查以下内容:

首先,我们为调用 api 调用以获取订单信息注册一个操作调用,我们通过突变存储响应,然后通过 getter 将其公开给我们的组件。

在路由器文件中,我们启用 props true 以便在组件中获取orderId,并使用该信息进行 api 调用,然后构建组件。

我希望我回答了你的问题,如果没有,请告诉我。 注意:请勿复制粘贴路由器代码,只需获取所需代码并根据需要进行调整

存储文件:

ACTIONS:

/* Get Order */
  GetOrder: ({ commit, dispatch }, orderId) => {
    return new Promise((resolve, reject) => {
      axios
        .get(`myapi/${orderId}`)
        .then((response) => {
          commit("SET_ORDER", response.data);
          resolve(response);
        })
    });
  }

MUTATION:
  SET_ORDER: (state, payload) => (state.order = payload)

STATE:
  order: null

GETTER:
  order: (state) => state.order

index.js(路由器)

{
    path: 'shop/orders/:orderId',
    name: 'Orders',
    component: AddMyComponentNameHere,
    props: (route) => {
      const orderId = Number.parseInt(route.params.orderId);
      return { orderId }
    }
  }

OrderComponent.vue

<template>
  <div v-if="order">
    {{ order.product.title }}
    {{ order.product.price }}
  </div>
</template>

props: {
    orderId: {
      required: true,
      type: Object,
    }
},

mounted() {
    this.$store.dispatch('shop/orders/', this.orderId)
  },
order() {
      return this.$store.getters.order;
    },

更新 我假设您已经使用吸气剂产品了。

当 api 调用完成后,我在产品列表中找到订单的产品 ID,当我找到它时,我将其保存到 order,然后我构建模板。 (您将需要调整键命名和可能的任何结构)

    computed:{return this.$store.getters.products},
 mounted() {
        this.$store.dispatch('shop/orders/', this.orderId).then(()=> this.order = this.products.find(product => product.id === this.order.productId); )
      },
data() {
    return {
      myProduct: null
}
}

  <template>
      <div v-if="order">
        {{ order.product.title }}
        {{ order.product.price }}
      </div>
    </template>

【讨论】:

  • 感谢您的回复,但我认为这并不能完全回答我的问题。获取订单数据已经可以了,但它只包含产品的 ID,而不是例如product.titleproduct.price 因为它们来自另一个 API。问题是如何连接两者,以便 {{ order.product.title }} 打印订单的 productTitle?
  • 我更新了我的评论,请检查一下。我相信逻辑是存在的,但是让我知道您可能需要的任何东西:)
【解决方案3】:

我认为有一个逻辑错误。如果您在订单页面中表示订单,则必须获取相关的产品数据以填充您的商店。但你可以懒惰地这样做。

<template>
  <div v-if="currentOrder">
    {{ currentOrder.product.title }} <!-- UNDEFINED -->
    {{ currentOrder.product.price }} <!-- UNDEFINED -->
  </div>
</template>

<script>
import {mapGetters} from 'vuex';

export default {
  name: "OrderDetail",
  data() {
    return {
      orderId: this.$route.params.id,
    }
  },
  computed: {
    ...mapGetters({
      currentOrder: 'shop/orders/order'
    })
  },
  mounted() {
    this.$store.dispatch('shop/orders/setOrderById', this.orderId);
    // Product check
    const hasNotProduct = !(this.currentOrder && this.currentOrder.product);
    if(hasNotProduct) {
     this.$store.dispatch('some/store/action/fetchProduct', this.orderId)
    }
  }
}
</script>

// some/store/action.js

fetchProductByOrderId({commit, dispatch}, orderId) {
  //fetchProduct By OrderId
  // dispatch action to merge product data and order data if your backend supported.
}

还有另一种选择。您可以在操作中一起获取订单和产品。但它的解决方案伴随着性能问题。我希望它会指导你

谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-30
    • 2020-09-12
    • 1970-01-01
    • 2019-03-03
    • 2019-11-11
    • 2014-01-08
    • 2015-06-10
    • 2018-01-04
    相关资源
    最近更新 更多