The problem background

In a single component, the hook execution order is beforeCreate-> created -> Mounted ->… ->destroyed, the parent component and the child component have their own hook functions. How and in what order will they be executed?

Parent-child component lifecycle execution sequence

Components, each of which prints logs in their hook functions to observe the order of execution. The result is as shown in the figure, the parent component is created first, then the child component is created; The child component is mounted first, then the parent component is mounted.

Parent beforeCreate-> parent CREATE -> child beforeCreate-> child created -> child Mounted -> parentCopy the code

After the child component is mounted, the parent component is not mounted. Therefore, when component data is displayed, API data is obtained in the parent component mounted, but the child component mounted cannot be obtained.

A closer look at the parent/child lifecycle hook sequence shows that the created hook is executed from the outside in, so the solution to passing the interface data to the parent/child component is:

  • A request is made for the data in the created component, which in turn receives the data in the child component’s created or Mounted.

Parent-child component lifecycle execution sequence

Loading the render process

Parent beforeCreate-> parent created-> parent beforeMount-> child beforeCreate-> child created-> child beforeMount-> Child Mounted -> parentCopy the code

The update process

Parent beforeUpdate-> child beforeUpdate-> child updated-> parent updatedCopy the code

Destruction of the process

Parent beforeDestroy-> child beforeDestroy-> child Destroyed -> parent DestroyedCopy the code

Common hook simple version

Parent CREATE -> child created-> child Mounted -> parentCopy the code

Adds a single component hook execution order

Activated, deactivated is a hook that is unique to a component when it is keep-alive

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. activated
  8. deactivated
  9. beforeDestroy
  10. destroyed
  11. errorCaptured

conclusion

  • When beforeCreate is executed: Data and EL are not initialized and the value is undefined
  • Created: The data object observed by the Vue instance is already configured, and the value of data is already available, but the root DOM element used by the Vue instance is not initialized
  • BeforeMount execution: Data and EL are initialized, but EL does not render data. The value of EL is “virtual” element nodes
  • Mounted: The EL has been rendered and mounted to the instance
  • BeforeUpdate and Updated trigger when the data in the EL is rendered, but the component DOM is updated only when the updated hook is called.
  • In the created hook, you can operate on data. At this time, you can make a data request and assign the returned data to the data
  • The Mounted hook manipulates the mounted DOM, and the DOM is rendered to the page.
  • Although the updated function is triggered when the data changes, it does not know exactly which attribute has changed, so in practice use computed or watch to listen for changes and do other things.
  • All lifecycle hooks automatically bind the this context to the instance, so you cannot define a lifecycle method using the arrow function (for example, created: () => this.fetchTodos()), which would cause this to point to the parent.
  • When using vue-Router to cache component state, the created hook is not called repeatedly. If our child component needs to do something each time it loads or switches state, we can use the Activated hook.
  • The parent and child hooks do not wait for the request to return, the request is asynchronous, and the VUE design cannot not execute the following hook because the request does not respond. Therefore, we must control the execution timing of the child component hook through v-IF

When a parent component passes interface data to a child component, make sure that the child component label is marked with v-if=” passed interface data “.

In the parent component of the created request to obtain data, through the prop passed to the child components. There is a problem with the child component taking data from the parent component in created or Mounted.

When the parent component calls the interface to pass data to the child component, the interface response is obviously asynchronous. This results in no matter which hook you make the request on the parent and which hook you receive the data on the child. You can’t get them. After the mounted of the child component has been executed, the request from the parent component will return data. Causes the data passed from the parent to the child to be undefined.

Solution 1:

When rendering the child component, add a condition that data1 is the data returned by the calling interface of the parent component. Render subcomponents when data is available. This creates a natural blockage. The child component’s created, mounted is executed only after the parent component’s created request returns data. Finally, the parent component mounted is executed.

<div class="test">
    <children v-if="data1" :data="data1" ></children>
</div>
Copy the code

Solution 2:

In the child component watch listens, the parent component gets the value, the value changes, naturally can be listened to

watch:{
    data: {deep:true.handler:function(newVal,oldVal) {
        this.$nextTick((a)= > {
          this.data = newVal
          this.data = newVal.url ? newVal.url : ' '}})}},Copy the code

Click the call interface from the parent component and display the child component, the child component gets the data and listens to call the method in watch and display it

The following are the subcomponents from which data1 is passed. In both created and Mounted, the datA1 returned by the parent component’s calling interface is not available. Only watch listens to Data1. And calls methods to render the child component.

props:['data1'].watch: {data1: {deep:true.handler:function(newVal,oldVal) {
        this.$nextTick((a)= > {
          this.data1 = newVal
          this.showData1(this.data1)
        })
      }
    },
}
Copy the code