I like mohghaderi's answer, but I ran into several issues with it, so I will use his sample code to show the changes I needed to make in order for it work. (In my own project, I'm using Vue 3 and the Options API.)
mohghaderi's Parent Component code with notes about my changes:
import ChildComponent from './components/ChildComponent'
new Vue({
  el: '#app',
  data: {
    item: {},
    childMethodsQueue: [],
  },
  // Note: In the template below, I added @child-methods-finished="childMethodsFinished" 
  //       as an event listener, so that we can reset the childMethodsQueue array to
  //       empty once the methods are finished.
  //       If you don't reset it, then the methods stay in there and cause problems.
  template: `
  <div>
     <ChildComponent :item="item" 
                     :methods-queue="childMethodsQueue"
                     @child-methods-finished="childMethodsFinished" />
     <button type="submit" @click.prevent="submit">Post</button>
  </div>
  `,
  methods: {
    submit() {
      this.childMethodsQueue.push({
        name: ChildComponent.methods.save.name,
        params: {}  // Note: delete the {} and put the name of your params, if you use a method that passes in params.
      })
    }
  },
  components: { ChildComponent },
})
mohghaderi's Child Component code with notes about my changes:
import { objectToString } from "@vue/shared"
export default {
    name: 'ChildComponent',
    props: {
      methodsQueue: { type: Array },
    },
    // Note:  I had to rewrite the watch option because it would not trigger.
    //        You have to add "deep, true" for arrays and objects.
    //        The function has to be called "handler" for it to work as well.
    watch: {
      methodsQueue: {
        handler() {
          this.processMethodsQueue()
        },
        deep: true,
      }
    },
    // Note:  Remove "mounted()" function if you don't want it to run on the mounted event.
    mounted() {
      this.processMethodsQueue()
    },
    methods: {
      save() {
          console.log("Child saved...")
      }, 
      processMethodsQueue() {
        if (!this.methodsQueue) return
        let len = this.methodsQueue.length
        if (!len) return  // Note:  This is required to prevent an infinite loop.
                          //        When we reset the childMethodsQueue array to empty,
                          //        it will trigger this method through the watch option,
                          //        so we need this in order to stop the cycle once we are done.
        // Note:  Instead of using ".shift()" to access an item in the array
        //        we need to use "[i]" otherwise we will get muliple calls of the method
        for (let i = 0; i < len; i++) {
          let method = this.methodsQueue[i]
          this[method.name](method.params)
        }
        // Note:  Now that we are done calling methods, we need to emit an event back to the parent
        //        so it can call it's method to reset the childMethodsQueue array to empty
        this.$emit('child-methods-finished')
      },
    },
  }