current position:Home>Vue2 cannot get the value in props in the data of the child component, or it is always the default value (the value of the parent component comes from asynchrony)

Vue2 cannot get the value in props in the data of the child component, or it is always the default value (the value of the parent component comes from asynchrony)

2022-04-29 16:17:58Wang yuanrou

Repetition problem

 For my convenience, I went directly to main.js Use in mockjs Simulate an interface request and set 2 Second response time 

mian.js

import Vue from "vue";
import App from "./App.vue";

const Mock = require("mockjs");
//  Response time of the request 2 second 
Mock.setup({
    
    timeout: "2000",
});

//  The request method should be in lowercase 
Mock.mock("/test", "get", {
    
    "msg|1-10": "*",
});

Vue.config.productionTip = false;

new Vue({
    
    render: (h) => h(App),
}).$mount("#app");
 The parent component will its own msg Pass to subcomponent , In the parent component msg Asynchronous tasks from interfaces .

Parent component

<template>
  <div>
    <HelloWorld :msg="msg" />
  </div>
</template>

<script> import HelloWorld from "./components/HelloWorld.vue"; import axios from "axios"; export default {
       name: "App", data() {
       return {
       msg: " The default value is ", }; }, components: {
       HelloWorld, }, created() {
       axios({
       method: "get", url: "/test", }).then(response => {
       console.log(response, "response"); this.msg = response.data.msg; }); }, }; </script>

<style></style>

 Subcomponent receive msg And show 

Child components

<template>
  <div>{
   { msg }}</div>
</template>

<script> export default {
       name: "HelloWorld", props: {
       msg: String, }, data() {
       return {
       msgSon: this.msg, }; }, mounted(){
       setInterval(() =>{
       console.log(this.msgSon) },1000) } }; </script>

<style scoped></style>

Running effect
 Insert picture description here

 Output at the beginning “ The default value is ” you 're right , But we found that after the interface returned , Parent component msg It has been modified , however 
 Subcomponents still output “ The default value is ”.

The analysis reason

 Because of the props The value of is assigned to data Not reactive ,props The value in has changed ,data The value in will not 
 Responsive change . Back to our article title :data Can't get props The value in , Maybe you are in the parent component 
 The value set in is undefined, But people think that I clearly assigned a value to it in the interface response , So everybody 
 Think it's a sub component props No value is obtained , In fact, it's just because when the sub components are rendered ,props
 Get the parent value in the component , But the value of the parent component at this time has not been returned in the interface , So it's just the default .

Solution

Use watch

 Think from the perspective of sub components : The value of the parent component has changed , But I don't know about subcomponents , No problem ,vue by 
 We provide watch, You can monitor whether a value changes , I use watch Listen to the value passed to me by your parent component , You one 
 Dan changed the value , I'll take mine data Just change the value copied from the .
<template>
  <div>{
   { msg }}</div>
</template>

<script> export default {
       name: "HelloWorld", props: {
       msg: String, }, data() {
       return {
       msgSon: this.msg, }; }, mounted() {
       setInterval(() => {
       console.log(this.msgSon); }, 1000); }, watch: {
       msg: function (newVal) {
       this.msgSon = newVal; }, }, }; </script>

<style scoped></style>

Running effect
 Insert picture description here

Use v-if

 Think from the perspective of sub components : I need to get value when rendering , But your parent component hasn't got the real value yet , that 
 I won't render it first , When you get the real value , Let me render , At this time, the value I get is not the real value .
<template>
  <div>
    <HelloWorld :msg="msg" v-if="lock"/>
  </div>
</template>

<script> import HelloWorld from "./components/HelloWorld.vue"; import axios from "axios"; export default {
       name: "App", data() {
       return {
       msg: " The default value is ", lock: false, }; }, components: {
       HelloWorld, }, created() {
       axios({
       method: "get", url: "/test", }).then(response => {
       console.log(response, "response"); this.msg = response.data.msg; this.lock = true; }); }, }; </script>

<style></style>

Running effect
 Insert picture description here

copyright notice
author[Wang yuanrou],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/119/202204291425343569.html

Random recommended