[Vuejs]-Vue.js Dynamically extend/replace child component method at runtime with access to parent scope

0👍

From what I managed to realize:

  • the solution in the code posted in the question really replaces the func() method in the child component. It’s just that Vue has already attached the old method to the html element. Replacing it at the source will have no impact.
    I was looking for a way to re-attach the eventListeners to html component. Re-rendering using an index key would not help because it will re-render the component with its original definition. You can hide the item in question for a split second, and when it appears you will receive an updated eventListener. However, this involves an intervention in the logic of the child component (which I avoid).
    The solution is the $forceUpdate() method.
    Thus, my code becomes the following:

// Foo.vue

<template>
    <button @click="func">Click me</button>
</template>

export default {
    methods: {
        func() {
            console.log('some xhr')
        }
    }
}

// Bar.vue

<template>
    <Foo ref="foo"/>
</template>

export default {
    components: {Foo}
    mounted() {
        this.$nextTick(() => {
            let original = this.$refs.foo.func; // preserve original function
            this.$refs.foo.func = function() {
                console.log('some conditional logic')
                original()
            }
            this.$refs.btn.$forceUpdate(); // will re-evaluate visual logic of child component
        })
    }
}

0👍

For this usecase a better implementation would be defining the function in the parent itself and passing it through props. Since props are by default reactive you can easily control it from parent.

// Foo.vue
<template>
    <button @click="clickFunction.handler">Click me</button>
</template>

export default {
  name: 'Foo',
  props: {
   clickFunction: {
     type: Object,
     required: true
   }
  }
}

// Bar.vue
<template>
    <Foo :clickFunction="propObject"/>
</template>

export default {
    components: {Foo},
    data() {
      return {
       propObject: {
        handler: null;
      }
     };
    }
    mounted() {
        this.$nextTick(() => {
          if(some condition) {
            this.propObject.handler = this.func();
          } else this.propObject.handler = null;
        })
    },
    methods: {
      func() {
            console.log('some xhr')
        }
  }
}

Leave a comment