vuejs parent 获取所有 child 数据后的事件

vuejs parent event once all child data is fetched

我是 vuejs 的新手,对于是否应该使用事件或 vuex 来了解何时从服务器获取所有 children 的数据仍然有些迷茫。

例如我有一个结构如下的路由:

<Parent>
   <Child1 />
   <Child2 />
   <Child3 />
</Parent>

然后在每个 child 组件中,我有一个 fetchData() 方法,它从不同端点从服务器检索数据:

export default {        
    created() {
      // fetch data
        this.fetchData()    
    },
    methods: {
        fetchData() {
            this.$http.get('/api/dataN', {})
                .then(response => {
                    // do something
                }).catch(error => {})
        }
    }
}

parent 如何知道一旦 所有 child 数据都已获取 因此 parent 可以执行操作?

我想让它成为一个通用函数,所以在另一条路线只有两个 children(或超过 3 个)的情况下,事件总是被触发。

我查看了 parent 挂钩,但似乎我在创建时获得了 child 数据(组件已加载),parent 挂钩对我没有用 - 因为据我所知。

我需要为 parent 修改 DOM 的示例:

你应该从每个子组件发出一个事件,父组件添加一个名为 nb_components 的数据 属性,它用组件的数量初始化,另一个 count 将递增每次子组件执行其任务时:

export default {

  created() {
    // fetch data
    this.fetchData()
  },
  methods: {
    fetchData() {
      this.$http.get('/api/dataN', {})
        .then(response => {
          this.$emit('fetch-data')
        }).catch(error => {})
    }
  }
}

和父组件:

<Parent>
  <Child1 @fetch-data="increment"  />
  <Child2 @fetch-data="increment"  />
  <Child3 @fetch-data="increment"  />
</Parent>

脚本

 data(){
       return{
         count:0,
         nb_components:3
         ....
        }
      },
  methods:{
       increment(){
          this.count++;
          if(this.count==this.nb_components){
                 //stop the spinner
             }
          }
    ...
  }

下面是一个使用异步回调函数的示例。每个子组件 returns 它自己的一个异步函数(例如 api 调用),父组件解析并保留一个 运行 触发回调次数的计数器:

Vue.component('child', {
  template: `<div>I take {{ timeout }} seconds to finish. <span>{{ message }}</span></div>`,
  props: ['callback'],
  data () {
    return {
      timeout: Math.ceil(Math.random() * 10),
      complete: false
    }
  },
  computed: {
    message () {
      return this.complete ? 'Done!' : 'Working...'
    }
  },
  mounted() {
    setTimeout(() => {
      this.complete = !this.complete
      
      const func = async () => {}
      
      this.callback.call(this, func)
    }, this.timeout * 1000)
  }
})

new Vue({
  el: '#app',
  data() {
    return {
      max: 10,
      counter: 0
    }
  },
  computed: {
    message () {
      return this.counter < this.max ? `${this.max - this.counter} Jobs remaining` : `All jobs complete!`
    }
  },
  methods: {
    async callback(func) {
      const data = await func()
      
      this.counter += 1
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <p>{{ message }}</p>
  <child v-for="i in max" :key="i" :callback="callback" style="margin: 1rem 0;"></child>
</div>

最后我做的略有不同:

  1. child 保持微调器的状态
  2. $emit 为 parent 提供回调 - 打开微调器 / 关

这不是我的完整代码,但为您提供了我如何解决它的示例。

<div id="app">
<div id="spinner" v-show="spinner" key=1></div>
  <child v-show="!spinner" @spinnerCallback="setSpinner" />
</div>

Vue.component('child', {
  template: `<div>this is child data</div>`,

  data() {
        return {
            tiles: '',
        }
    },
    created() {
      // start spinner
      this.$emit('spinnerCallback', 1)

      //fetch data
        this.fetchData()
    },
    methods: {
        fetchData() {
            this.$http.get('/api/dashboard', {})
                .then(response => {
                    this.tiles = response.data.tiles//,
                    this.$emit('spinnerCallback', 0)
                }).catch(error => {})
        }
    }
})

var app = new Vue({
  el: '#app',
    data() {
        return {
            spinner: null,
        }
    },
    methods: {
        setSpinner: function(value) {
          // toggle spinner
          if (value == 1) {
            this.spinner = true;
          } else {
            this.spinner = false;
          }
        }
    },
})