Vuejs - 子组件方法在父查询完成运行之前运行

时间:2018-04-15 06:47:02

标签: javascript vuejs2 components

我正在开发一个基本的POC应用程序,该应用程序在正面找到产品的Solr搜索功能,然后搜索结果中的链接使用路由转到产品详细信息页面。

index.js

import Vue from 'vue'
import Router from 'vue-router'
import Search from '@/components/Search'
import Product from '@/components/Product'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/search',
      name: 'Search',
      component: Search
    },
    {
      path: '/product_display/:language/:entity_id',
      name: 'product_display',
      component: Product
    },
  ]
})

Product.vue

<template>
  <section class="hero is-warning">
  <div class="hero-body">
    <div class="container">
      <h1 class="title">
        {{ product.ss_field_content_title }}
      </h1>
    </div>
  </div>
  <section class="section">
    <div class="container">
      <productSlideshow :slideshowNid="product.is_product_slideshow" 
      :language="product.ss_language"></productSlideshow>
    </div>
  </section>
</section>
</template>

<script>
import axios from 'axios'
import ProductSlideshow from '@/components/ProductSlideshow'

export default {
  name: 'Product',
  components: {
    ProductSlideshow
  },
  data () {
    return {
      product: {}
    }
  },
  created () {
    this.getProduct()
  },
  methods: {
    getProduct: function () {
      const params = new URLSearchParams()
      var entityId = this.$route.params.entity_id
      var language = this.$route.params.language
      params.append('fq', 'bundle:product_display')
      params.append('fq', 'entity_id:' + entityId)
      params.append('fq', 'ss_language:' + language)
      params.append('wt', 'json')
      params.append('rows', 1)
      axios.get('https://my.solrurl.com/solr/indexname/select', {
        params: params
      })
      .then(response => {
        this.product = response.data.response.docs[0]
      })
      .catch(e => {
        this.errors.push(e)
      })
    }
  },
  watch: {
    '$route': 'getProduct'
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

访问此页面工作正常。问题是为子ProductSlideshow组件获取必要的参数。

<template>
  <h1>{{ slideshow.label }}</h1>
</template>

<script>
import axios from 'axios'

export default {
  name: 'ProductSlideshow',
  props: {
    slideshowNid: {
      type: Number,
      required: true
    },
    language: {
      type: String,
      required: true
    }
  },
  data () {
    return {
      slideshow: {},
      slides: {}
    }
  },
  created () {
    this.getSlideshow()
  },
  methods: {
    getSlideshow: function () {
      var language = this.language
      // Get slideshow record from Solr.
      const params = new URLSearchParams()
      params.append('fq', 'bundle:slideshow')
      params.append('fq', 'entity_id:' + this.slideshowNid)
      params.append('fq', 'ss_language:' + language)
      params.append('fq', 'entity_type:node')
      params.append('wt', 'json')
      params.append('rows', 1)
      axios.get('https://my.solrurl.com/solr/indexname/select', {
        params: params
      })
      .then(response => {
        this.slideshow = response.data.response.docs[0]
        this.slides = this.slideshow.sm_field_slideshow_home
      })
    }
  },
  watch: {
    '$route': 'getSlideshow'
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

我所看到的是没有从幻灯片记录的Solr查询返回的数据,并且在检查Solr查询时,这是因为语言在查询中未定义,所以没有什么可以被退回通过使用各种调试器断点,我发现发生了什么是在从产品中的 getProduct()返回结果之前调用了 getSlideshow()零件。我尝试删除ProductDisplay组件中的 created()方法,但这并没有什么区别。

我需要更改哪些内容,以便在ProductSlideshow组件中的 getSlideshow()方法在产品组件的查询完成之前不会被调用?

1 个答案:

答案 0 :(得分:0)

您的问题与事实相关,即Vue以同步方式触发created挂钩,因此在API响应到来之前创建并装载所有子模板。 解决方案是使用Conditional Rendering

Product.vue组件中创建一些布尔值,如isProductFetched,并仅在此值为true时呈现子项。

<template>
  <section class="hero is-warning">
  <div class="hero-body">
    <div class="container">
      <h1 class="title">
        {{ product.ss_field_content_title }}
      </h1>
    </div>
  </div>
  <section class="section">
    <div class="container">
      <productSlideshow 
      v-if="isProductFetched"
      :slideshowNid="product.is_product_slideshow" 
      :language="product.ss_language"></productSlideshow>
    </div>
  </section>
</section>
</template>

<script>
import axios from 'axios'
import ProductSlideshow from '@/components/ProductSlideshow'

export default {
  name: 'Product',
  components: {
    ProductSlideshow
  },
  data () {
    return {
     isProductFetched: false,
     product: {}
    }
  },
  created () {
    this.getProduct()
  },
  methods: {
    getProduct: function () {
      const params = new URLSearchParams()
      var entityId = this.$route.params.entity_id
      var language = this.$route.params.language
      params.append('fq', 'bundle:product_display')
      params.append('fq', 'entity_id:' + entityId)
      params.append('fq', 'ss_language:' + language)
      params.append('wt', 'json')
      params.append('rows', 1)
      axios.get('https://my.solrurl.com/solr/indexname/select', {
        params: params
      })
      .then(response => {
        this.product = response.data.response.docs[0]

        // At this point, the product is fetched
       this.isProductFetched = true
      })
      .catch(e => {
        this.errors.push(e)
      })
    }
  },
  watch: {
    '$route': 'getProduct'
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

因此,在此值变为true.之前,不会呈现子组件。此外,不要忘记处理错误情况。