Problem description

The parent component obtains asynchronous data through Promise and other asynchronous methods and passes it to the child component. The child component directly displays no problem. If the data is processed, the data it gets is the initial value of the parent component.

Cause analysis,

The parent component obtains asynchronous data through Promise and other asynchronous methods. Before the data is returned, the child component created has been executed, so the data in the child component is the data of the parent component last time.

Lifecycle of parent and child components: Load the rendering process

Parent beforeCreate - > parent created - > parent beforeMount - > child beforeCreate - > child created - > child beforeMount - > child Mounted - > parent MountedCopy the code

Second, sub-component update process

Parent beforeUpdate --> Child beforeUpdate --> Child updated --> Parent updatedCopy the code

Destruction process

Parent beforeDestroy --> Child beforeDestroy --> Child destroyed --> Parent destroyedCopy the code

To solve

Methods a

The parent component

  <child :child-data="asyncData" v-if="asyncData"></child>
Copy the code

Load the child components when asyncData is worth it.

Evaluation: When asyncData is an object or array element and the child component obtains object attributes or an array element, the above method is feasible (no error will be reported), but there will still be slow data loading and display (and the child component will first display the value passed by the last parent component, then render the value passed by the current parent component).

Method 2

Child components

Watch :{childData(val){console.log(' childData processing ',val)}}Copy the code

Evaluation: The above methods still have the problem of slow data loading in method 1.

Methods three

Subcomponent Watch computed Data combined

<template> <div> subcomponent <p>{{test}}</p> </div> </template> <script> export default {props: ['tableData'], data: () => ({ test: '' }), watch: { tableData (val) { this.dataResult = val } }, computed: { dataResult : { set (value) { this.update() this.test = value }, get () { return this.test } } }, methods: {update () {console.log(this.childobject) // {items: [1,2,3]}}}} </script>Copy the code

Methods four

Use a combination of EMIT, ON, and bus

<template> <div> subcomponent <p>{{test}}</p> </div> </template> <script> export default {props: ['childObject'], data: () => ({ test: '}), created () {/ / binding this. $bus. On (' triggerChild ', (parmas) => { this.test = parmas.items[0] // 1 this.updata() }) }, methods: { updata () { console.log(this.test) // 1 } } } </script>Copy the code

Using the bus library, parent.vue and child.vue must share an event bus (that is, introduce the same JS that defines something like let bus = new vue () for the two components to connect) in order to trigger each other.

Other methods

The data is stored in store, and the child component listens for changes in the data (Watch /computed).

Other scenarios

Asynchronous data retrieval errors can occur in various scenarios, such as:

  • Render dom according to the data, and when there is JS operation on dom, because not render out and can not find the corresponding DOM element error, here can use vue to provide$nextTick()Function, or you can do it manuallysetTimeoutTimer, delay acquisition;
  • When using Better-Scroll, because the DOM is not rendered, the height of the scroll element cannot be obtained, so the scroll cannot be initialized. You can also use the function provided by Vue to initialize the scroll after the DOM is rendered.