Recently, I was reviewing my vUE knowledge while preparing for an interview. I saw some articles on “how to implement the parent component to listen to the life cycle of the child component”. Here are two ways to implement this requirement

Methods a

Using the $emit

/ / the parent component
<template>
  <div>
    <Child
      @mounted="onMounted"
      @updated="onUpdated"
      @beforeDestroy="onBeforeDestroy"
    ></Child>
  </div>
</template>

/ / child component. mounted () {this.$emit('mounted')
  }
  updated () {
	  this.$emit('updated')
  }
  beforeDestroy () {
	  this.$emit('beforeDestroy')}...Copy the code

The parent component passes multiple callback functions to the child component, depending on the child component to call the parent component’s life callback function through the VM.$emit method in its own life cycle. This approach basically meets our needs, but it still feels a little clunky. If a subcomponent is a reference to a third party library, there is no way to implement callbacks in its life cycle.

Method 2

Using the @ hook:

/ / the parent component
<template>
  <div>
    <Child
      @hook:mounted="onMounted"
      @hook:updated="onUpdated"
      @hook:beforeDestroy="onBeforeDestroy"
    ></Child>
  </div>
</template>

/ / child component<! - no - >Copy the code

Add @hook:mounted=”onMounted” to the parent component. What’s the hook?

There isn’t much explanation in the official documentation, but we see hooks in programmatic event listeners in this introduction. Since the child component can trigger the @hook: binding event of the parent component without any code, we assume that this must be implemented in the vue logic. So we tried to find out in the source code.

In the lifecycle. Js file, we find that each phase of the vue lifecycle calls a callHook function that supports two inputs, the instance VM and the corresponding lifecycle hook name. $emit(‘hook:’ + hook); $emit(‘hook:’ + hook); So the clever part of method two is to reuse the logic of Vue itself.

$on(‘hook:mounted’); The vue instance itself executes vm.$emit(‘hook: Mounted ‘) during its life cycle, which triggers the callback function we bound to the child component. This is how @hook: works, but the official documentation in Vue2.0 does not formally introduce the API.

expand

Hook: We can also make some usage extensions that can sometimes improve the simplicity of our code.

When writing a component, we often need to do some processing for the business logic in each lifecycle, and the business is scattered in various lifecycle hooks:

<script type="text/ecmascript-6">
export default {
  mounted () {
      // Perform some service A-related logic during mounting
      // Perform some service B-related logic during mounting
  }
  updated () {
      // Perform some business A logic when updating
      // Perform some business B logic when updating
      // Perform some business C logic when updating
  }
  beforeDestroy () {
    // Perform some business A logic when destroying
    // Perform some business C logic when destroying
  }
}
</script>
Copy the code

Business logic is scattered in various life cycles, and sometimes it is not conducive for us to read the code, especially when the business is a long and complex code. At this time, we can consider using Hook: to comb a certain piece of business code and improve the readability:

<script type="text/ecmascript-6">
export default {
  created() {
    this.$on('hook:mounted'.() = >{perform some business A related logic while mounting})this.$on('hook:updated'.() = >{perform some business A related logic while mounting})this.$once('hook:beforeDestroy'.() = >})}} </script>Copy the code

This way, you can write all the scattered business logic in a single Created hook function while maintaining the original lifecycle logic.

In addition, another usage scenario is more common, for instance, we in the writing component will perform some event listeners or timer function, we can hope to have destroyed in the component to destroy these listening or timer, but due to praise the life cycle of problems, often will be assigned to a timer global variables, or to bind to this, It then retrieves and performs the destruction operation in another lifecycle.

/ / before optimization
<script type="text/ecmascript-6">
export default {
  data() {
    return {
        timer:null
      }
  }
  mounted () {
    this.timer = setInterval(() = > {
	// todo
    }, 1000);
  }
  beforeDestroy () {
    clearInterval(this.timer)
  }
}
</script>


/ / after optimization
<script type="text/ecmascript-6">
export default {
  mounted () {
    const timer = setInterval(() = > {
	// todo
    }, 1000);
    this.$once('hook:beforeDestroy'.function () {
        clearInterval(timer)
    })
  }
}
</script>
Copy the code

As you can see, after optimization, we can avoid many useless variable definitions in data.