Сегодня я столкнулся с небольшой ямой в общении между родительским и дочерним компонентами, разработанными Vue.Ситуация следующая: дочерний компонент использует echart для отображения диаграммы, необходимые опции передаются родительским компонентом через prop, начальный значение опций в родительском компоненте пустое, а в смонтированном хуке функция Инициировать http запрос на получение данных и потом обновить опции В результате подкомпонент не может корректно отобразить график После недолгих поисков проблема решена.Я сделаю запись по этой статье.Я также надеюсь помочь друзьям, которые столкнутся с той же проблемой в будущем.Демо используется в качестве примера.
родительский компонент
<template>
<div id="app">
<child :message="message"></child>
</div>
</template>
<script>
import child from "./components/child";
export default {
name: "app",
components: {child },
data() {
return {
message:{}
};
},
mounted(){
// 模拟异步请求
setTimeout( () => this.message.age = 18,2000)
}
};
</script>
Подсборка
<template>
<div>{{age}}</div>
</template>
<script type='text/ecmascript-6'>
export default {
props: ["message"],
mounted(){
// 模拟echart的初始化操作
this.age = this.message.age
},
data() {
return {
age: null
};
}
};
</script>
Фактический эффект показан на рисунке
На самом деле подкомпонент здесь получает обновленное значение, если шаблон{{message.age}}
Он может отображать 18, но опции передаются в проекте, а в подкомпоненте есть операция setOptions echart, которая напрямую не выводит данные пропа, поэтому демка написана так. Вот где можно проанализировать проблему, значение из родительского компонента при монтировании дочернего компонентаmessage
пустой объект,this.message.age
Он не определен, поэтому страница отображается как пустая.Через 2 секунды значение родительского компонента обновляется, и дочерний компонент может получить новое значение, но функция смонтированного хука больше не срабатывает, поэтомуage
Все еще не определено, я проверил это в Интернете, обычное решение - использоватьwatch
следить за проп. Улучшенный код выглядит следующим образом
Подсборка
<template>
<div>{{age}}</div>
</template>
<script type='text/ecmascript-6'>
export default {
props: ["message"],
mounted() {
this.age = this.message.age;
},
watch: {
message(nv,ov){
this.age = nv.age
}
},
data() {
return {
age: null
};
}
};
</script>
По сути, это конец онлайн-руководства, и подкомпоненты могут отображаться правильно, но... моя страница все та же, она все еще пуста, проверьте инструмент отладки, она все еще такая:
Потираю, что это за хрень, отлаживал и обнаружил, что код в часах вообще не будет выполняться, но сообщение явно изменилось, поэтому я некоторое время бродил по интернету, а потом увидел такой абзац.
Vue добавит каждое свойство в данные при создании экземпляраgetter setter
Чтобы добиться адаптивного обновления, но недавно добавленные свойства не могут обеспечить адаптивное обновление, здесь начальное значение сообщения в нашем родительском компоненте равно{}
, Установите его возраст равным 18 через 2 секунды, потому что возраст — это новое свойство, и геттер и сеттер не были добавлены к возрасту при инициализации экземпляра, поэтому часы не удались. Вот картинка с официального сайта украдена
Измените код, чтобы добавить возраст к начальному значению сообщения в родительском компоненте.
<template>
<div id="app">
<child :message="message"></child>
</div>
</template>
<script>
import child from "./components/child";
export default {
name: "app",
components: {child },
data() {
return {
message:{age:null}
};
},
mounted(){
// 模拟异步请求
setTimeout( () => this.message.age = 18,2000)
}
};
</script>
Ну, это не должно быть проблемой, откройте страницу, а. . . до сих пор знакомая страница
Небольшой срыв, успокойтесь и анализируйте очередную волну. Дочерний компонент просматривает сообщение, но мы выполняем его в асинхронном коде.this.message.age = 18
вместо чего-то вродеthis.message = xxx
В этой операции, хотя объект сообщения действительно изменился, сеттер не может быть запущен, и часы не будут работать.Я проверил официальный сайт и нашел эту конфигурацию:
Измените код следующим образом:
<template>
<div>{{age}}</div>
</template>
<script type='text/ecmascript-6'>
export default {
props: ["message"],
mounted() {
this.age = this.message.age;
},
watch: {
message: {
deep: true,
handler(nv, ov) {
this.age = nv.age;
}
}
},
data() {
return {
age: null
};
}
};
</script>
открыть страницу снова
ну конец цветочка!!!